|
35 | 35 | import org.apache.lucene.search.LeafCollector;
|
36 | 36 | import org.apache.lucene.search.MatchAllDocsQuery;
|
37 | 37 | import org.apache.lucene.search.MatchNoDocsQuery;
|
| 38 | +import org.apache.lucene.search.PhraseQuery; |
38 | 39 | import org.apache.lucene.search.Pruning;
|
39 | 40 | import org.apache.lucene.search.Query;
|
40 | 41 | import org.apache.lucene.search.Sort;
|
|
48 | 49 | import org.opensearch.action.search.SearchShardTask;
|
49 | 50 | import org.opensearch.common.settings.Settings;
|
50 | 51 | import org.opensearch.common.xcontent.json.JsonXContent;
|
| 52 | +import org.opensearch.core.index.Index; |
51 | 53 | import org.opensearch.core.xcontent.ToXContent;
|
52 | 54 | import org.opensearch.core.xcontent.XContentBuilder;
|
| 55 | +import org.opensearch.index.mapper.DocumentMapper; |
| 56 | +import org.opensearch.index.mapper.MatchOnlyTextFieldMapper; |
53 | 57 | import org.opensearch.index.mapper.NumberFieldMapper.NumberFieldType;
|
54 | 58 | import org.opensearch.index.mapper.NumberFieldMapper.NumberType;
|
| 59 | +import org.opensearch.index.mapper.SourceFieldMapper; |
| 60 | +import org.opensearch.index.mapper.TextSearchInfo; |
55 | 61 | import org.opensearch.index.query.ParsedQuery;
|
56 | 62 | import org.opensearch.index.query.QueryShardContext;
|
| 63 | +import org.opensearch.index.query.SourceFieldMatchQuery; |
57 | 64 | import org.opensearch.index.shard.IndexShard;
|
58 | 65 | import org.opensearch.index.shard.IndexShardTestCase;
|
59 | 66 | import org.opensearch.lucene.queries.MinDocQuery;
|
|
62 | 69 | import org.opensearch.search.internal.ContextIndexSearcher;
|
63 | 70 | import org.opensearch.search.internal.ScrollContext;
|
64 | 71 | import org.opensearch.search.internal.SearchContext;
|
| 72 | +import org.opensearch.search.lookup.LeafSearchLookup; |
| 73 | +import org.opensearch.search.lookup.SearchLookup; |
| 74 | +import org.opensearch.search.lookup.SourceLookup; |
65 | 75 | import org.opensearch.search.profile.ProfileResult;
|
66 | 76 | import org.opensearch.search.profile.ProfileShardResult;
|
67 | 77 | import org.opensearch.search.profile.SearchProfileShardResults;
|
|
80 | 90 | import java.util.Collection;
|
81 | 91 | import java.util.Collections;
|
82 | 92 | import java.util.List;
|
| 93 | +import java.util.Set; |
83 | 94 | import java.util.concurrent.ExecutorService;
|
84 | 95 | import java.util.concurrent.Executors;
|
85 | 96 | import java.util.concurrent.TimeUnit;
|
|
94 | 105 | import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
95 | 106 | import static org.hamcrest.Matchers.hasSize;
|
96 | 107 | import static org.hamcrest.Matchers.instanceOf;
|
| 108 | +import static org.mockito.ArgumentMatchers.any; |
97 | 109 | import static org.mockito.Mockito.mock;
|
98 | 110 | import static org.mockito.Mockito.when;
|
99 | 111 |
|
@@ -1514,6 +1526,90 @@ public void testCollapseQuerySearchResults() throws Exception {
|
1514 | 1526 | dir.close();
|
1515 | 1527 | }
|
1516 | 1528 |
|
| 1529 | + public void testSourceFieldMatchQueryWithProfile() throws Exception { |
| 1530 | + Directory dir = newDirectory(); |
| 1531 | + IndexWriterConfig iwc = newIndexWriterConfig(); |
| 1532 | + RandomIndexWriter w = new RandomIndexWriter(random(), dir, iwc); |
| 1533 | + w.close(); |
| 1534 | + IndexReader reader = DirectoryReader.open(dir); |
| 1535 | + QueryShardContext queryShardContext = mock(QueryShardContext.class); |
| 1536 | + DocumentMapper mockDocumentMapper = mock(DocumentMapper.class); |
| 1537 | + SourceFieldMapper mockSourceMapper = mock(SourceFieldMapper.class); |
| 1538 | + SearchLookup searchLookup = mock(SearchLookup.class); |
| 1539 | + LeafSearchLookup leafSearchLookup = mock(LeafSearchLookup.class); |
| 1540 | + |
| 1541 | + when(queryShardContext.sourcePath("foo")).thenReturn(Set.of("bar")); |
| 1542 | + when(queryShardContext.index()).thenReturn(new Index("test_index", "uuid")); |
| 1543 | + when(searchLookup.getLeafSearchLookup(any())).thenReturn(leafSearchLookup); |
| 1544 | + when(leafSearchLookup.source()).thenReturn(new SourceLookup()); |
| 1545 | + when(mockSourceMapper.enabled()).thenReturn(true); |
| 1546 | + when(mockDocumentMapper.sourceMapper()).thenReturn(mockSourceMapper); |
| 1547 | + when(queryShardContext.documentMapper(any())).thenReturn(mockDocumentMapper); |
| 1548 | + when(queryShardContext.lookup()).thenReturn(searchLookup); |
| 1549 | + |
| 1550 | + TestSearchContext context = new TestSearchContext(queryShardContext, indexShard, newContextSearcher(reader, executor)); |
| 1551 | + context.parsedQuery( |
| 1552 | + new ParsedQuery( |
| 1553 | + new SourceFieldMatchQuery( |
| 1554 | + new TermQuery(new Term("foo", "bar")), |
| 1555 | + new PhraseQuery("foo", "bar", "baz"), |
| 1556 | + new MatchOnlyTextFieldMapper.MatchOnlyTextFieldType( |
| 1557 | + "user", |
| 1558 | + true, |
| 1559 | + true, |
| 1560 | + TextSearchInfo.WHITESPACE_MATCH_ONLY, |
| 1561 | + Collections.emptyMap() |
| 1562 | + ), |
| 1563 | + queryShardContext |
| 1564 | + ) |
| 1565 | + ) |
| 1566 | + ); |
| 1567 | + |
| 1568 | + context.setTask(new SearchShardTask(123L, "", "", "", null, Collections.emptyMap())); |
| 1569 | + context.setSize(1); |
| 1570 | + context.trackTotalHitsUpTo(5); |
| 1571 | + QueryPhase.executeInternal(context.withCleanQueryResult().withProfilers(), queryPhaseSearcher); |
| 1572 | + assertProfileData(context, "SourceFieldMatchQuery", query -> { |
| 1573 | + assertThat(query.getTimeBreakdown().keySet(), not(empty())); |
| 1574 | + assertThat(query.getTimeBreakdown().get("score"), equalTo(0L)); |
| 1575 | + assertThat(query.getTimeBreakdown().get("score_count"), equalTo(0L)); |
| 1576 | + if (executor != null) { |
| 1577 | + long maxScore = query.getTimeBreakdown().get("max_score"); |
| 1578 | + long minScore = query.getTimeBreakdown().get("min_score"); |
| 1579 | + long avgScore = query.getTimeBreakdown().get("avg_score"); |
| 1580 | + long maxScoreCount = query.getTimeBreakdown().get("max_score_count"); |
| 1581 | + long minScoreCount = query.getTimeBreakdown().get("min_score_count"); |
| 1582 | + long avgScoreCount = query.getTimeBreakdown().get("avg_score_count"); |
| 1583 | + assertThat(maxScore, equalTo(0L)); |
| 1584 | + assertThat(minScore, equalTo(0L)); |
| 1585 | + assertThat(avgScore, equalTo(0L)); |
| 1586 | + assertThat(maxScore, equalTo(avgScore)); |
| 1587 | + assertThat(avgScore, equalTo(minScore)); |
| 1588 | + assertThat(maxScoreCount, equalTo(0L)); |
| 1589 | + assertThat(minScoreCount, equalTo(0L)); |
| 1590 | + assertThat(avgScoreCount, equalTo(0L)); |
| 1591 | + assertThat(maxScoreCount, equalTo(avgScoreCount)); |
| 1592 | + assertThat(avgScoreCount, equalTo(minScoreCount)); |
| 1593 | + } |
| 1594 | + assertThat(query.getTimeBreakdown().get("create_weight"), greaterThan(0L)); |
| 1595 | + assertThat(query.getTimeBreakdown().get("create_weight_count"), equalTo(1L)); |
| 1596 | + assertThat(query.getProfiledChildren(), empty()); |
| 1597 | + }, collector -> { |
| 1598 | + assertThat(collector.getReason(), equalTo("search_top_hits")); |
| 1599 | + assertThat(collector.getTime(), greaterThan(0L)); |
| 1600 | + if (collector.getName().contains("CollectorManager")) { |
| 1601 | + assertThat(collector.getReduceTime(), greaterThan(0L)); |
| 1602 | + } |
| 1603 | + assertThat(collector.getMaxSliceTime(), greaterThan(0L)); |
| 1604 | + assertThat(collector.getMinSliceTime(), greaterThan(0L)); |
| 1605 | + assertThat(collector.getAvgSliceTime(), greaterThan(0L)); |
| 1606 | + assertThat(collector.getSliceCount(), greaterThanOrEqualTo(1)); |
| 1607 | + assertThat(collector.getProfiledChildren(), empty()); |
| 1608 | + }); |
| 1609 | + reader.close(); |
| 1610 | + dir.close(); |
| 1611 | + } |
| 1612 | + |
1517 | 1613 | private void assertProfileData(SearchContext context, String type, Consumer<ProfileResult> query, Consumer<CollectorResult> collector)
|
1518 | 1614 | throws IOException {
|
1519 | 1615 | assertProfileData(context, collector, (profileResult) -> {
|
|
0 commit comments