/** * Checks the result of {@link QueryBuilder#toQuery(QueryShardContext)} given the original {@link QueryBuilder} * and {@link QueryShardContext}. Verifies that named queries and boost are properly handled and delegates to * {@link #doAssertLuceneQuery(AbstractQueryBuilder, Query, SearchContext)} for query specific checks. */ private void assertLuceneQuery(QB queryBuilder, Query query, SearchContext context) throws IOException { if (queryBuilder.queryName() != null) { Query namedQuery = context.getQueryShardContext().copyNamedQueries().get(queryBuilder.queryName()); assertThat(namedQuery, equalTo(query)); } if (query != null) { if (queryBuilder.boost() != AbstractQueryBuilder.DEFAULT_BOOST) { assertThat(query, either(instanceOf(BoostQuery.class)).or(instanceOf(SpanBoostQuery.class))); if (query instanceof SpanBoostQuery) { SpanBoostQuery spanBoostQuery = (SpanBoostQuery) query; assertThat(spanBoostQuery.getBoost(), equalTo(queryBuilder.boost())); query = spanBoostQuery.getQuery(); } else { BoostQuery boostQuery = (BoostQuery) query; assertThat(boostQuery.getBoost(), equalTo(queryBuilder.boost())); query = boostQuery.getQuery(); } } } doAssertLuceneQuery(queryBuilder, query, context); }
public void testToQueryWithStringField() throws IOException { assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0); String query = "{\n" + " \"fuzzy\":{\n" + " \"" + STRING_FIELD_NAME + "\":{\n" + " \"value\":\"sh\",\n" + " \"fuzziness\": \"AUTO\",\n" + " \"prefix_length\":1,\n" + " \"boost\":2.0\n" + " }\n" + " }\n" + "}"; Query parsedQuery = parseQuery(query).toQuery(createShardContext()); assertThat(parsedQuery, instanceOf(BoostQuery.class)); BoostQuery boostQuery = (BoostQuery) parsedQuery; assertThat(boostQuery.getBoost(), equalTo(2.0f)); assertThat(boostQuery.getQuery(), instanceOf(FuzzyQuery.class)); FuzzyQuery fuzzyQuery = (FuzzyQuery) boostQuery.getQuery(); assertThat(fuzzyQuery.getTerm(), equalTo(new Term(STRING_FIELD_NAME, "sh"))); assertThat(fuzzyQuery.getMaxEdits(), equalTo(Fuzziness.AUTO.asDistance("sh"))); assertThat(fuzzyQuery.getPrefixLength(), equalTo(1)); }
public void testToQueryPhraseQueryBoostAndSlop() throws IOException { assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0); QueryStringQueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder("\"test phrase\"~2").field(STRING_FIELD_NAME, 5f); Query query = queryStringQueryBuilder.toQuery(createShardContext()); assertThat(query, instanceOf(DisjunctionMaxQuery.class)); DisjunctionMaxQuery disjunctionMaxQuery = (DisjunctionMaxQuery) query; assertThat(disjunctionMaxQuery.getDisjuncts().size(), equalTo(1)); assertThat(disjunctionMaxQuery.getDisjuncts().get(0), instanceOf(BoostQuery.class)); BoostQuery boostQuery = (BoostQuery) disjunctionMaxQuery.getDisjuncts().get(0); assertThat(boostQuery.getBoost(), equalTo(5f)); assertThat(boostQuery.getQuery(), instanceOf(PhraseQuery.class)); PhraseQuery phraseQuery = (PhraseQuery) boostQuery.getQuery(); assertThat(phraseQuery.getSlop(), Matchers.equalTo(2)); assertThat(phraseQuery.getTerms().length, equalTo(2)); }
public void testToQueryBoost() throws IOException { assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0); QueryShardContext shardContext = createShardContext(); MultiMatchQueryBuilder multiMatchQueryBuilder = new MultiMatchQueryBuilder("test"); multiMatchQueryBuilder.field(STRING_FIELD_NAME, 5f); Query query = multiMatchQueryBuilder.toQuery(shardContext); assertTermOrBoostQuery(query, STRING_FIELD_NAME, "test", 5f); multiMatchQueryBuilder = new MultiMatchQueryBuilder("test"); multiMatchQueryBuilder.field(STRING_FIELD_NAME, 5f); multiMatchQueryBuilder.boost(2f); query = multiMatchQueryBuilder.toQuery(shardContext); assertThat(query, instanceOf(BoostQuery.class)); BoostQuery boostQuery = (BoostQuery) query; assertThat(boostQuery.getBoost(), equalTo(2f)); assertTermOrBoostQuery(boostQuery.getQuery(), STRING_FIELD_NAME, "test", 5f); }
public void testCrossFieldMultiMatchQuery() throws IOException { QueryShardContext queryShardContext = indexService.newQueryShardContext( randomInt(20), null, () -> { throw new UnsupportedOperationException(); }); queryShardContext.setAllowUnmappedFields(true); Query parsedQuery = multiMatchQuery("banon").field("name.first", 2).field("name.last", 3).field("foobar").type(MultiMatchQueryBuilder.Type.CROSS_FIELDS).toQuery(queryShardContext); try (Engine.Searcher searcher = indexService.getShard(0).acquireSearcher("test")) { Query rewrittenQuery = searcher.searcher().rewrite(parsedQuery); BooleanQuery.Builder expected = new BooleanQuery.Builder(); expected.add(new TermQuery(new Term("foobar", "banon")), BooleanClause.Occur.SHOULD); Query tq1 = new BoostQuery(new TermQuery(new Term("name.first", "banon")), 2); Query tq2 = new BoostQuery(new TermQuery(new Term("name.last", "banon")), 3); expected.add(new DisjunctionMaxQuery(Arrays.<Query>asList(tq1, tq2), 0f), BooleanClause.Occur.SHOULD); assertEquals(expected.build(), rewrittenQuery); } }
public void testBlendNoTermQuery() { FakeFieldType ft1 = new FakeFieldType(); ft1.setName("foo"); FakeFieldType ft2 = new FakeFieldType() { @Override public Query termQuery(Object value, QueryShardContext context) { return new MatchAllDocsQuery(); } }; ft2.setName("bar"); Term[] terms = new Term[] { new Term("foo", "baz") }; float[] boosts = new float[] {2}; Query expectedClause1 = BlendedTermQuery.booleanBlendedQuery(terms, boosts, false); Query expectedClause2 = new BoostQuery(new MatchAllDocsQuery(), 3); Query expected = new BooleanQuery.Builder().setDisableCoord(true) .add(expectedClause1, Occur.SHOULD) .add(expectedClause2, Occur.SHOULD) .build(); Query actual = MultiMatchQuery.blendTerm( indexService.newQueryShardContext(randomInt(20), null, () -> { throw new UnsupportedOperationException(); }), new BytesRef("baz"), null, 1f, new FieldAndFieldType(ft1, 2), new FieldAndFieldType(ft2, 3)); assertEquals(expected, actual); }
@Test public void testBoost() throws Exception { CharacterRunAutomaton stopWords = new CharacterRunAutomaton(Automata.makeString("on")); Analyzer oneStopAnalyzer = new MockAnalyzer(random(), MockTokenizer.SIMPLE, true, stopWords); QueryParser qp = getParserConfig(oneStopAnalyzer); Query q = getQuery("on^1.0", qp); Assert.assertNotNull(q); q = getQuery("\"hello\"^2.0", qp); Assert.assertNotNull(q); Assert.assertEquals(((BoostQuery) q).getBoost(), (float) 2.0, (float) 0.5); q = getQuery("hello^2.0", qp); Assert.assertNotNull(q); Assert.assertEquals(((BoostQuery) q).getBoost(), (float) 2.0, (float) 0.5); q = getQuery("\"on\"^1.0", qp); Assert.assertNotNull(q); Analyzer a2 = new MockAnalyzer(random(), MockTokenizer.SIMPLE, true, MockTokenFilter.ENGLISH_STOPSET); QueryParser qp2 = getParserConfig(a2); q = getQuery("the^3", qp2); // "the" is a stop word so the result is an empty query: Assert.assertNotNull(q); assertMatchNoDocsQuery(q); Assert.assertFalse(q instanceof BoostQuery); }
@Test public void testStopwords() throws Exception { CharacterRunAutomaton stopSet = new CharacterRunAutomaton(new RegExp("the|foo").toAutomaton()); QueryParser qp = getParserConfig(new MockAnalyzer(random(), MockTokenizer.SIMPLE, true, stopSet)); Query result = getQuery("field:the OR field:foo", qp); Assert.assertNotNull("result is null and it shouldn't be", result); Assert.assertTrue("result is not a BooleanQuery", result instanceof BooleanQuery || result instanceof MatchNoDocsQuery); if (result instanceof BooleanQuery) { Assert.assertEquals(0, ((BooleanQuery) result).clauses().size()); } result = getQuery("field:woo OR field:the", qp); Assert.assertNotNull("result is null and it shouldn't be", result); Assert.assertTrue("result is not a TermQuery", result instanceof TermQuery); result = getQuery("(fieldX:xxxxx OR fieldy:xxxxxxxx)^2 AND (fieldx:the OR fieldy:foo)", qp); Assert.assertNotNull("result is null and it shouldn't be", result); Assert.assertTrue("result is not a BoostQuery", result instanceof BoostQuery); result = ((BoostQuery) result).getQuery(); Assert.assertTrue("result is not a BooleanQuery", result instanceof BooleanQuery); if (VERBOSE) System.out.println("Result: " + result); Assert.assertTrue(((BooleanQuery) result).clauses().size() + " does not equal: " + 2, ((BooleanQuery) result).clauses().size() == 2); }
public void testBoost() throws Exception { CharacterRunAutomaton stopWords = new CharacterRunAutomaton(Automata.makeString("on")); Analyzer oneStopAnalyzer = new MockAnalyzer(random(), MockTokenizer.SIMPLE, true, stopWords); CommonQueryParserConfiguration qp = getParserConfig(oneStopAnalyzer); Query q = getQuery("on^1.0",qp); assertNotNull(q); q = getQuery("\"hello\"^2.0",qp); assertNotNull(q); assertEquals(getBoost(q), (float) 2.0, (float) 0.5); q = getQuery("hello^2.0",qp); assertNotNull(q); assertEquals(((BoostQuery)q).getBoost(), (float) 2.0, (float) 0.5); q = getQuery("\"on\"^1.0",qp); assertNotNull(q); Analyzer a2 = new MockAnalyzer(random(), MockTokenizer.SIMPLE, true, MockTokenFilter.ENGLISH_STOPSET); CommonQueryParserConfiguration qp2 = getParserConfig(a2); q = getQuery("the^3", qp2); // "the" is a stop word so the result is an empty query: assertNotNull(q); assertEmpty(q); assertEquals(1.0f, getBoost(q), 0.01f); }
public void testStopwords() throws Exception { CharacterRunAutomaton stopSet = new CharacterRunAutomaton(new RegExp("the|foo").toAutomaton()); CommonQueryParserConfiguration qp = getParserConfig(new MockAnalyzer(random(), MockTokenizer.SIMPLE, true, stopSet)); Query result = getQuery("field:the OR field:foo",qp); assertNotNull("result is null and it shouldn't be", result); System.out.println(result.getClass()); assertTrue("result is not a BooleanQuery", result instanceof SpanOrQuery || result instanceof BooleanQuery || result instanceof MatchNoDocsQuery); if (result instanceof BooleanQuery) { assertEquals(0, ((BooleanQuery) result).clauses().size()); } result = getQuery("field:woo OR field:the",qp); assertNotNull("result is null and it shouldn't be", result); assertTrue("result is not a TermQuery", result instanceof TermQuery); result = getQuery("(fieldX:xxxxx OR fieldy:xxxxxxxx)^2 AND (fieldx:the OR fieldy:foo)",qp); assertNotNull("result is null and it shouldn't be", result); assertTrue("result is not a BoostQuery", result instanceof BoostQuery); result = ((BoostQuery) result).getQuery(); assertTrue("result is not a BooleanQuery", result instanceof BooleanQuery); if (VERBOSE) System.out.println("Result: " + result); assertTrue(((BooleanQuery) result).clauses().size() + " does not equal: " + 2, ((BooleanQuery) result).clauses().size() == 2); }
public void testExtractQueryMetadata_boostQuery() { TermQuery termQuery1 = new TermQuery(new Term("_field", "_term")); BoostQuery constantScoreQuery = new BoostQuery(termQuery1, 1f); Result result = analyze(constantScoreQuery); assertThat(result.verified, is(true)); List<Term> terms = new ArrayList<>(result.terms); assertThat(terms.size(), equalTo(1)); assertThat(terms.get(0).field(), equalTo(termQuery1.getTerm().field())); assertThat(terms.get(0).bytes(), equalTo(termQuery1.getTerm().bytes())); }
protected static void assertTermOrBoostQuery(Query query, String field, String value, float fieldBoost) { if (fieldBoost != AbstractQueryBuilder.DEFAULT_BOOST) { assertThat(query, instanceOf(BoostQuery.class)); BoostQuery boostQuery = (BoostQuery) query; assertThat(boostQuery.getBoost(), equalTo(fieldBoost)); query = boostQuery.getQuery(); } assertTermQuery(query, field, value); }
private Query applyBoost(String field, Query q) { Float fieldBoost = settings.fieldsAndWeights().get(field); if (fieldBoost != null && fieldBoost != 1f) { return new BoostQuery(q, fieldBoost); } return q; }
/** Returns true if the given query might match nested documents. */ public boolean mightMatchNestedDocs(Query query) { if (query instanceof ConstantScoreQuery) { return mightMatchNestedDocs(((ConstantScoreQuery) query).getQuery()); } else if (query instanceof BoostQuery) { return mightMatchNestedDocs(((BoostQuery) query).getQuery()); } else if (query instanceof MatchAllDocsQuery) { return true; } else if (query instanceof MatchNoDocsQuery) { return false; } else if (query instanceof TermQuery) { // We only handle term queries and range queries, which should already // cover a high majority of use-cases return mightMatchNestedDocs(((TermQuery) query).getTerm().field()); } else if (query instanceof PointRangeQuery) { return mightMatchNestedDocs(((PointRangeQuery) query).getField()); } else if (query instanceof IndexOrDocValuesQuery) { return mightMatchNestedDocs(((IndexOrDocValuesQuery) query).getIndexQuery()); } else if (query instanceof BooleanQuery) { final BooleanQuery bq = (BooleanQuery) query; final boolean hasRequiredClauses = bq.clauses().stream().anyMatch(BooleanClause::isRequired); if (hasRequiredClauses) { return bq.clauses().stream() .filter(BooleanClause::isRequired) .map(BooleanClause::getQuery) .allMatch(this::mightMatchNestedDocs); } else { return bq.clauses().stream() .filter(c -> c.getOccur() == Occur.SHOULD) .map(BooleanClause::getQuery) .anyMatch(this::mightMatchNestedDocs); } } else if (query instanceof ESToParentBlockJoinQuery) { return ((ESToParentBlockJoinQuery) query).getPath() != null; } else { return true; } }
/** Returns true if the given query might match parent documents or documents * that are nested under a different path. */ public boolean mightMatchNonNestedDocs(Query query, String nestedPath) { if (query instanceof ConstantScoreQuery) { return mightMatchNonNestedDocs(((ConstantScoreQuery) query).getQuery(), nestedPath); } else if (query instanceof BoostQuery) { return mightMatchNonNestedDocs(((BoostQuery) query).getQuery(), nestedPath); } else if (query instanceof MatchAllDocsQuery) { return true; } else if (query instanceof MatchNoDocsQuery) { return false; } else if (query instanceof TermQuery) { return mightMatchNonNestedDocs(((TermQuery) query).getTerm().field(), nestedPath); } else if (query instanceof PointRangeQuery) { return mightMatchNonNestedDocs(((PointRangeQuery) query).getField(), nestedPath); } else if (query instanceof IndexOrDocValuesQuery) { return mightMatchNonNestedDocs(((IndexOrDocValuesQuery) query).getIndexQuery(), nestedPath); } else if (query instanceof BooleanQuery) { final BooleanQuery bq = (BooleanQuery) query; final boolean hasRequiredClauses = bq.clauses().stream().anyMatch(BooleanClause::isRequired); if (hasRequiredClauses) { return bq.clauses().stream() .filter(BooleanClause::isRequired) .map(BooleanClause::getQuery) .allMatch(q -> mightMatchNonNestedDocs(q, nestedPath)); } else { return bq.clauses().stream() .filter(c -> c.getOccur() == Occur.SHOULD) .map(BooleanClause::getQuery) .anyMatch(q -> mightMatchNonNestedDocs(q, nestedPath)); } } else { return true; } }
@Override public Query termQuery(Object value, QueryShardContext context) { failIfNotIndexed(); TermQuery query = new TermQuery(new Term(name(), indexedValueForSearch(value))); if (boost() == 1f || (context != null && context.indexVersionCreated().before(Version.V_5_0_0_alpha1))) { return query; } return new BoostQuery(query, boost()); }
public void testToQueryBooleanQueryMultipleBoosts() throws Exception { assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0); int numBoosts = randomIntBetween(2, 10); float[] boosts = new float[numBoosts + 1]; String queryStringPrefix = ""; String queryStringSuffix = ""; for (int i = 0; i < boosts.length - 1; i++) { float boost = 2.0f / randomIntBetween(3, 20); boosts[i] = boost; queryStringPrefix += "("; queryStringSuffix += ")^" + boost; } String queryString = queryStringPrefix + "foo bar" + queryStringSuffix; float mainBoost = 2.0f / randomIntBetween(3, 20); boosts[boosts.length - 1] = mainBoost; QueryStringQueryBuilder queryStringQueryBuilder = new QueryStringQueryBuilder(queryString).field(STRING_FIELD_NAME) .minimumShouldMatch("2").boost(mainBoost); Query query = queryStringQueryBuilder.toQuery(createShardContext()); for (int i = boosts.length - 1; i >= 0; i--) { assertThat(query, instanceOf(BoostQuery.class)); BoostQuery boostQuery = (BoostQuery) query; assertThat(boostQuery.getBoost(), equalTo(boosts[i])); query = boostQuery.getQuery(); } assertThat(query, instanceOf(BooleanQuery.class)); BooleanQuery booleanQuery = (BooleanQuery) query; assertThat(booleanQuery.getMinimumNumberShouldMatch(), equalTo(2)); assertThat(booleanQuery.clauses().get(0).getOccur(), equalTo(BooleanClause.Occur.SHOULD)); assertThat(booleanQuery.clauses().get(0).getQuery(), equalTo(new TermQuery(new Term(STRING_FIELD_NAME, "foo")))); assertThat(booleanQuery.clauses().get(1).getOccur(), equalTo(BooleanClause.Occur.SHOULD)); assertThat(booleanQuery.clauses().get(1).getQuery(), equalTo(new TermQuery(new Term(STRING_FIELD_NAME, "bar")))); }
public void testToQueryInnerPrefixQuery() throws Exception { assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0); String queryAsString = "{\n" + " \"dis_max\":{\n" + " \"queries\":[\n" + " {\n" + " \"prefix\":{\n" + " \"" + STRING_FIELD_NAME + "\":{\n" + " \"value\":\"sh\",\n" + " \"boost\":1.2\n" + " }\n" + " }\n" + " }\n" + " ]\n" + " }\n" + "}"; Query query = parseQuery(queryAsString).toQuery(createShardContext()); assertThat(query, instanceOf(DisjunctionMaxQuery.class)); DisjunctionMaxQuery disjunctionMaxQuery = (DisjunctionMaxQuery) query; List<Query> disjuncts = disjunctionMaxQuery.getDisjuncts(); assertThat(disjuncts.size(), equalTo(1)); assertThat(disjuncts.get(0), instanceOf(BoostQuery.class)); BoostQuery boostQuery = (BoostQuery) disjuncts.get(0); assertThat((double) boostQuery.getBoost(), closeTo(1.2, 0.00001)); assertThat(boostQuery.getQuery(), instanceOf(PrefixQuery.class)); PrefixQuery firstQ = (PrefixQuery) boostQuery.getQuery(); // since age is automatically registered in data, we encode it as numeric assertThat(firstQ.getPrefix(), equalTo(new Term(STRING_FIELD_NAME, "sh"))); }
@Override protected void doAssertLuceneQuery(MultiMatchQueryBuilder queryBuilder, Query query, SearchContext context) throws IOException { // we rely on integration tests for deeper checks here assertThat(query, either(instanceOf(BoostQuery.class)).or(instanceOf(TermQuery.class)).or(instanceOf(AllTermQuery.class)) .or(instanceOf(BooleanQuery.class)).or(instanceOf(DisjunctionMaxQuery.class)) .or(instanceOf(FuzzyQuery.class)).or(instanceOf(MultiPhrasePrefixQuery.class)) .or(instanceOf(MatchAllDocsQuery.class)).or(instanceOf(ExtendedCommonTermsQuery.class)) .or(instanceOf(MatchNoDocsQuery.class)).or(instanceOf(PhraseQuery.class)) .or(instanceOf(LegacyNumericRangeQuery.class)) .or(instanceOf(PointRangeQuery.class)).or(instanceOf(IndexOrDocValuesQuery.class))); }
private Tuple<RankerQuery, HitLogConsumer> extractQuery(LoggingSearchExtBuilder.LogSpec logSpec, Map<String, Query> namedQueries) { Query q = namedQueries.get(logSpec.getNamedQuery()); if (q == null) { throw new IllegalArgumentException("No query named [" + logSpec.getNamedQuery() + "] found"); } final RankerQuery query; return toLogger(logSpec, inspectQuery(q) .orElseThrow(() -> new IllegalArgumentException("Query named [" + logSpec.getNamedQuery() + "] must be a [sltr] query [" + ((q instanceof BoostQuery) ? ((BoostQuery)q).getQuery().getClass().getSimpleName() : q.getClass().getSimpleName()) + "] found"))); }
private Optional<RankerQuery> inspectQuery(Query q) { if (q instanceof RankerQuery) { return Optional.of((RankerQuery) q); } else if (q instanceof BoostQuery && ((BoostQuery) q).getQuery() instanceof RankerQuery) { return Optional.of((RankerQuery) ((BoostQuery) q).getQuery()); } return Optional.empty(); }
@SuppressWarnings("unchecked") public static String queryToString(Query luceneQuery) { StringBuilder sb = new StringBuilder(); if (luceneQuery instanceof BooleanQuery) { sb.append(formatBooleanQuery((BooleanQuery) luceneQuery)); } else if (luceneQuery instanceof TermQuery) { sb.append(formatTermQuery((TermQuery) luceneQuery)); } else if (luceneQuery instanceof RawLuceneQuery) { sb.append(formatRawLuceneQuery((RawLuceneQuery) luceneQuery)); } else if (luceneQuery instanceof FuzzyQuery) { sb.append(formatFuzzyQuery((FuzzyQuery) luceneQuery)); } else if (luceneQuery instanceof PrefixQuery) { sb.append(formatPrefixQuery((PrefixQuery) luceneQuery)); } else if (luceneQuery instanceof WildcardQuery) { sb.append(formatWildcardQuery((WildcardQuery) luceneQuery)); } else if (luceneQuery instanceof NumericRangeQuery) { sb.append(formatNumericRangeQuery((NumericRangeQuery<? extends Number>) luceneQuery)); } else if (luceneQuery instanceof IToQueryStringAwareLuceneQuery) { sb.append(((IToQueryStringAwareLuceneQuery) luceneQuery).toQueryString()); } else if (luceneQuery instanceof BoostQuery) { sb.append(queryToString(((BoostQuery) luceneQuery).getQuery())); sb.append(BOOST_PARAMETER_PREFIX); sb.append(((BoostQuery) luceneQuery).getBoost()); } else { throw new IllegalStateException(String.format("Query of type %1$s not supported", luceneQuery.getClass().getName())); } return sb.toString(); }
@Override public Query termQuery(Object value, QueryShardContext context) { failIfNotIndexed(); TermQuery query = new TermQuery(new Term(name(), indexedValueForSearch(value))); if ((Float.compare(boost(), 1f) == 0) || (context != null && context.indexVersionCreated().before(Version.V_5_0_0_alpha1))) { return query; } return new BoostQuery(query, boost()); }
@SafeVarargs public DMQMatcher(float boost, float tieBreaker, TypeSafeMatcher<? extends Query>... disjuncts) { super((boost == 1f) ? DisjunctionMaxQuery.class : BoostQuery.class); this.boost = boost; this.tieBreaker = tieBreaker; this.disjuncts = disjuncts; }
@Override protected boolean matchesSafely(Query query) { BooleanQuery bq = null; if (query instanceof BoostQuery) { Query boostedQuery = ((BoostQuery) query).getQuery(); if (!(boostedQuery instanceof BooleanQuery)) { return false; } if (((BoostQuery) query).getBoost() != boost) { return false; } bq = (BooleanQuery) boostedQuery; } else if (!(query instanceof BooleanQuery)) { return false; } else { if (boost != 1f) { return false; } bq = (BooleanQuery) query; } return matchBooleanQuery(bq); }
public PhraseQueryMatcher(float boost, final String field, final String[] terms, final int slop) { super((boost == 1f) ? PhraseQuery.class : BoostQuery.class); this.field = field; this.slop = slop; this.terms = terms; this.boost = boost; }
private Float getBoost(Query q) { if (q instanceof BoostQuery) { return ((BoostQuery)q).getBoost(); } else if (q instanceof SpanBoostQuery) { return ((SpanBoostQuery)q).getBoost(); } return 1.0f; }
public void testSynonymsPhrase() throws Exception { MultiPhraseQuery.Builder expectedQ = new MultiPhraseQuery.Builder(); expectedQ.add(new Term(FIELD, "old")); expectedQ.add(new Term[] { new Term(FIELD, "dogs"), new Term(FIELD, "dog") }); QueryParser qp = new QueryParser(FIELD, new MockSynonymAnalyzer()); assertEquals(expectedQ, qp.parse("\"old dogs\"")); qp.setDefaultOperator(Operator.AND); assertEquals(expectedQ, qp.parse("\"old dogs\"")); BoostQuery expected = new BoostQuery(expectedQ.build(), 2f); assertEquals(expected, qp.parse("\"old dogs\"^2")); expectedQ.setSlop(3); assertEquals(expected, qp.parse("\"old dogs\"~3^2")); }
public void testCJKSynonymsPhrase() throws Exception { MultiPhraseQuery.Builder expectedQ = new MultiPhraseQuery.Builder(); expectedQ.add(new Term(FIELD, "中")); expectedQ.add(new Term[] { new Term(FIELD, "国"), new Term(FIELD, "國")}); QueryParser qp = new QueryParser(FIELD, new MockCJKSynonymAnalyzer()); qp.setDefaultOperator(Operator.AND); assertEquals(expectedQ, qp.parse("\"中国\"")); Query expected = new BoostQuery(expectedQ.build(), 2f); assertEquals(expected, qp.parse("\"中国\"^2")); expectedQ.setSlop(3); assertEquals(expected, qp.parse("\"中国\"~3^2")); }
@Test public void testBoostQuery() throws Throwable { Document doc1 = new Document(); doc1.add(new TextField("fieldA", "Dit is veld a", Store.NO)); doc1.add(new TextField("fieldB", "This is field b", Store.NO)); lucene.addDocument("id:1", doc1); Document doc2 = new Document(); doc2.add(new TextField("fieldA", "This is field a", Store.NO)); doc2.add(new TextField("fieldB", "Dit is veld b", Store.NO)); lucene.addDocument("id:2", doc2); BooleanQuery.Builder builder = new BooleanQuery.Builder(); builder.add(new BoostQuery(new TermQuery(new Term("fieldA", "field")), 200), Occur.SHOULD); builder.add(new BoostQuery(new TermQuery(new Term("fieldB", "field")), 0.2f), Occur.SHOULD); LuceneResponse response = lucene.executeQuery(builder.build()); assertEquals(2, response.hits.size()); assertEquals("id:2", response.hits.get(0).id); assertEquals("id:1", response.hits.get(1).id); builder = new BooleanQuery.Builder(); builder.add(new BoostQuery(new TermQuery(new Term("fieldA", "field")), 0.2f), Occur.SHOULD); builder.add(new BoostQuery(new TermQuery(new Term("fieldB", "field")), 200), Occur.SHOULD); response = lucene.executeQuery(builder.build()); assertEquals(2, response.hits.size()); assertEquals("id:1", response.hits.get(0).id); assertEquals("id:2", response.hits.get(1).id); }
@Test public void testBooleanShouldQuery() { JsonObject json = Json.createObjectBuilder() .add("query", Json.createObjectBuilder() .add("type", "BooleanQuery") .add("clauses", Json.createArrayBuilder() .add(Json.createObjectBuilder() .add("type", "TermQuery") .add("boost", 1.0) .add("occur", "SHOULD") .add("term", Json.createObjectBuilder() .add("field", "aField") .add("value", "value"))) .add(Json.createObjectBuilder() .add("type", "TermQuery") .add("boost", 2.0) .add("occur", "SHOULD") .add("term", Json.createObjectBuilder() .add("field", "oField") .add("value", "value"))))) .build(); QueryData q = new QueryData(new StringReader(json.toString()), queryConverter); TermQuery aQuery = new TermQuery(new Term("aField", "value")); TermQuery oQuery = new TermQuery(new Term("oField", "value")); BooleanQuery.Builder query = new BooleanQuery.Builder(); query.add(new BoostQuery(aQuery, 1.0f), Occur.SHOULD); query.add(new BoostQuery(oQuery, 2.0f), Occur.SHOULD); assertEquals(query.build(), q.query); }
@Test public void testBooleanMustQuery() { JsonObject json = Json.createObjectBuilder() .add("query", Json.createObjectBuilder() .add("type", "BooleanQuery") .add("clauses", Json.createArrayBuilder() .add(Json.createObjectBuilder() .add("type", "TermQuery") .add("boost", 1.0) .add("occur", "MUST") .add("term", Json.createObjectBuilder() .add("field", "aField") .add("value", "value"))) .add(Json.createObjectBuilder() .add("type", "TermQuery") .add("boost", 2.0) .add("occur", "MUST_NOT") .add("term", Json.createObjectBuilder() .add("field", "oField") .add("value", "value"))))) .build(); QueryData q = new QueryData(new StringReader(json.toString()), queryConverter); TermQuery aQuery = new TermQuery(new Term("aField", "value")); TermQuery oQuery = new TermQuery(new Term("oField", "value")); BooleanQuery.Builder query = new BooleanQuery.Builder(); query.add(new BoostQuery(aQuery, 1.0f), Occur.MUST); query.add(new BoostQuery(oQuery, 2.0f), Occur.MUST_NOT); assertEquals(query.build(), q.query); }
static Function<Query, Result> boostQuery() { return query -> { Query wrappedQuery = ((BoostQuery) query).getQuery(); return analyze(wrappedQuery); }; }
@Override void flatten(Query sourceQuery, IndexReader reader, Collection<Query> flatQueries, float boost) throws IOException { if (sourceQuery instanceof BoostQuery) { BoostQuery bq = (BoostQuery) sourceQuery; sourceQuery = bq.getQuery(); boost *= bq.getBoost(); flatten(sourceQuery, reader, flatQueries, boost); } else if (sourceQuery instanceof SpanTermQuery) { super.flatten(new TermQuery(((SpanTermQuery) sourceQuery).getTerm()), reader, flatQueries, boost); } else if (sourceQuery instanceof ConstantScoreQuery) { flatten(((ConstantScoreQuery) sourceQuery).getQuery(), reader, flatQueries, boost); } else if (sourceQuery instanceof FunctionScoreQuery) { flatten(((FunctionScoreQuery) sourceQuery).getSubQuery(), reader, flatQueries, boost); } else if (sourceQuery instanceof MultiPhrasePrefixQuery) { flatten(sourceQuery.rewrite(reader), reader, flatQueries, boost); } else if (sourceQuery instanceof FiltersFunctionScoreQuery) { flatten(((FiltersFunctionScoreQuery) sourceQuery).getSubQuery(), reader, flatQueries, boost); } else if (sourceQuery instanceof MultiPhraseQuery) { MultiPhraseQuery q = ((MultiPhraseQuery) sourceQuery); convertMultiPhraseQuery(0, new int[q.getTermArrays().length], q, q.getTermArrays(), q.getPositions(), reader, flatQueries); } else if (sourceQuery instanceof BlendedTermQuery) { final BlendedTermQuery blendedTermQuery = (BlendedTermQuery) sourceQuery; flatten(blendedTermQuery.rewrite(reader), reader, flatQueries, boost); } else if (sourceQuery instanceof ESToParentBlockJoinQuery) { ESToParentBlockJoinQuery blockJoinQuery = (ESToParentBlockJoinQuery) sourceQuery; flatten(blockJoinQuery.getChildQuery(), reader, flatQueries, boost); } else if (sourceQuery instanceof BoostingQuery) { BoostingQuery boostingQuery = (BoostingQuery) sourceQuery; //flatten positive query with query boost flatten(boostingQuery.getMatch(), reader, flatQueries, boost); //flatten negative query with negative boost flatten(boostingQuery.getContext(), reader, flatQueries, boostingQuery.getBoost()); } else if (sourceQuery instanceof SynonymQuery) { // SynonymQuery should be handled by the parent class directly. // This statement should be removed when https://issues.apache.org/jira/browse/LUCENE-7484 is merged. SynonymQuery synQuery = (SynonymQuery) sourceQuery; for (Term term : synQuery.getTerms()) { flatten(new TermQuery(term), reader, flatQueries, boost); } } else { super.flatten(sourceQuery, reader, flatQueries, boost); } }
private static Query wrapWithBoost(Query query, float boost) { if (boost != AbstractQueryBuilder.DEFAULT_BOOST) { return new BoostQuery(query, boost); } return query; }
/** * @param q parsed Lucene query string query * @return a rewritten query with nested queries for custom properties (when in nested mode) */ private static QueryBuilder rewriteQuery(Query q, int depth) throws IllegalAccessException { if (depth > MAX_QUERY_DEPTH) { throw new IllegalArgumentException("`Query depth exceeded! Max depth: " + MAX_QUERY_DEPTH); } QueryBuilder qb = null; if (q instanceof BooleanQuery) { qb = boolQuery(); for (BooleanClause clause : ((BooleanQuery) q).clauses()) { switch (clause.getOccur()) { case MUST: ((BoolQueryBuilder) qb).must(rewriteQuery(clause.getQuery(), depth++)); break; case MUST_NOT: ((BoolQueryBuilder) qb).mustNot(rewriteQuery(clause.getQuery(), depth++)); break; case FILTER: ((BoolQueryBuilder) qb).filter(rewriteQuery(clause.getQuery(), depth++)); break; case SHOULD: default: ((BoolQueryBuilder) qb).should(rewriteQuery(clause.getQuery(), depth++)); } } } else if (q instanceof TermRangeQuery) { qb = termRange(q); } else if (q instanceof BoostQuery) { qb = rewriteQuery(((BoostQuery) q).getQuery(), depth++).boost(((BoostQuery) q).getBoost()); } else if (q instanceof TermQuery) { qb = term(q); } else if (q instanceof FuzzyQuery) { qb = fuzzy(q); } else if (q instanceof PrefixQuery) { qb = prefix(q); } else if (q instanceof WildcardQuery) { qb = wildcard(q); } else { logger.warn("Unknown query type in nested mode query syntax: {}", q.getClass()); } return (qb == null) ? matchAllQuery() : qb; }
@Test public void testBooleanQueryToString() throws ParseException { BooleanQuery.Builder bq1Builder = new BooleanQuery.Builder(); TermQuery queryTerm = new TermQuery(new Term("field1", "text1")); BoostQuery query = new BoostQuery(queryTerm, 2.0f); bq1Builder.add(query, Occur.MUST); bq1Builder.add(new TermQuery(new Term("field2", "text2")), Occur.MUST_NOT); BooleanQuery.Builder bq2Builder = new BooleanQuery.Builder(); bq2Builder.add(new FuzzyQuery(new Term("field3", "text3"), 1), Occur.MUST); bq2Builder.add(new FuzzyQuery(new Term("field4", "text4"), 2), Occur.SHOULD); bq2Builder.add(new TermQuery(new Term("field4", "text4")), Occur.SHOULD); bq2Builder.add(new WildcardQuery(new Term("field8", "t*t?")), Occur.MUST); BooleanQuery.Builder bq3Builder = new BooleanQuery.Builder(); bq3Builder.add(new PrefixQuery(new Term("field5", "text5")), Occur.SHOULD); bq3Builder.add(new PrefixQuery(new Term("field6", "text6")), Occur.MUST_NOT); BooleanQuery.Builder bq4Builder = new BooleanQuery.Builder(); bq4Builder.add(new WildcardQuery(new Term("field7", "text?")), Occur.SHOULD); bq4Builder.add(new WildcardQuery(new Term("field8", "t*t?")), Occur.MUST); BooleanQuery.Builder bq5Builder = new BooleanQuery.Builder(); bq5Builder.add(new TermQuery(new Term("", "text9")), Occur.MUST_NOT); bq5Builder.add(new TermQuery(new Term("", "text10")), Occur.SHOULD); BooleanQuery.Builder bq6Builder = new BooleanQuery.Builder(); bq6Builder.add(new TermQuery(new Term("", "text11")), Occur.MUST_NOT); bq6Builder.add(new TermQuery(new Term("", "text12")), Occur.MUST); BooleanQuery bq6Boolean = bq6Builder.build(); BoostQuery bq6 = new BoostQuery(bq6Boolean, 0.8f); BooleanQuery.Builder finalQueryBuilder = new BooleanQuery.Builder(); finalQueryBuilder.add(bq1Builder.build(), Occur.MUST); finalQueryBuilder.add(bq2Builder.build(), Occur.SHOULD); finalQueryBuilder.add(bq3Builder.build(), Occur.MUST_NOT); finalQueryBuilder.add(bq4Builder.build(), Occur.SHOULD); finalQueryBuilder.add(bq5Builder.build(), Occur.MUST); finalQueryBuilder.add(bq6, Occur.SHOULD); String stringQuery = LuceneUtils.queryToString(finalQueryBuilder.build()); QueryParser parser = new QueryParser("", new StandardAnalyzer()); Query parsedQuery = parser.parse(stringQuery); assertEquals(parser.parse(finalQueryBuilder.build().toString()), parsedQuery); }
public BQMatcher(float boost, int mm, ClauseMatcher... clauses) { super((boost == 1f) ? BooleanQuery.class : BoostQuery.class); this.clauses = clauses; this.boost = boost; this.mm = mm; }
/** * Wrap a query with a {@link BoostQuery} if the boost factor doesn't equal 1. * * @param query The query to boost * @param boostFactor The boost factor * @return A BoostQuery if boostFactor != 1 or the original query in all other cases. */ public static Query boost(Query query, float boostFactor) { return boostFactor == 1f ? query : new BoostQuery(query, boostFactor); }