@Override public Query rewrite(IndexReader reader) throws IOException { Query rewritten = super.rewrite(reader); if (rewritten != this) { return rewritten; } if (termArrays.isEmpty()) { return new MatchNoDocsQuery(); } MultiPhraseQuery.Builder query = new MultiPhraseQuery.Builder(); query.setSlop(slop); int sizeMinus1 = termArrays.size() - 1; for (int i = 0; i < sizeMinus1; i++) { query.add(termArrays.get(i), positions.get(i)); } Term[] suffixTerms = termArrays.get(sizeMinus1); int position = positions.get(sizeMinus1); ObjectHashSet<Term> terms = new ObjectHashSet<>(); for (Term term : suffixTerms) { getPrefixTerms(terms, term, reader); if (terms.size() > maxExpansions) { break; } } if (terms.isEmpty()) { return Queries.newMatchNoDocsQuery(); } query.add(terms.toArray(Term.class), position); return query.build(); }
// TODO: Move to QueryParserTestBase once standard flexible parser gets this capability public void testMultiWordSynonyms() throws Exception { QueryParser dumb = new QueryParser("field", new Analyzer1()); dumb.setSplitOnWhitespace(false); // A multi-word synonym source will form a synonym query for the same-starting-position tokens BooleanQuery.Builder multiWordExpandedBqBuilder = new BooleanQuery.Builder(); Query multiWordSynonymQuery = new SynonymQuery(new Term("field", "guinea"), new Term("field", "cavy")); multiWordExpandedBqBuilder.add(multiWordSynonymQuery, BooleanClause.Occur.SHOULD); multiWordExpandedBqBuilder.add( new TermQuery(new Term("field", "pig")), BooleanClause.Occur.SHOULD); Query multiWordExpandedBq = multiWordExpandedBqBuilder.build(); assertEquals(multiWordExpandedBq, dumb.parse("guinea pig")); // With the phrase operator, a multi-word synonym source will form a multiphrase query. // When the number of expanded term(s) is different from that of the original term(s), this is // not good. MultiPhraseQuery.Builder multiWordExpandedMpqBuilder = new MultiPhraseQuery.Builder(); multiWordExpandedMpqBuilder.add( new Term[] {new Term("field", "guinea"), new Term("field", "cavy")}); multiWordExpandedMpqBuilder.add(new Term("field", "pig")); Query multiWordExpandedMPQ = multiWordExpandedMpqBuilder.build(); assertEquals(multiWordExpandedMPQ, dumb.parse("\"guinea pig\"")); // custom behavior, the synonyms are expanded, unless you use quote operator QueryParser smart = new SmartQueryParser(); smart.setSplitOnWhitespace(false); assertEquals(multiWordExpandedBq, smart.parse("guinea pig")); PhraseQuery.Builder multiWordUnexpandedPqBuilder = new PhraseQuery.Builder(); multiWordUnexpandedPqBuilder.add(new Term("field", "guinea")); multiWordUnexpandedPqBuilder.add(new Term("field", "pig")); Query multiWordUnexpandedPq = multiWordUnexpandedPqBuilder.build(); assertEquals(multiWordUnexpandedPq, smart.parse("\"guinea pig\"")); }
/** forms multiphrase query */ public void testSynonymsPhrase() throws Exception { MultiPhraseQuery.Builder expectedBuilder = new MultiPhraseQuery.Builder(); expectedBuilder.add(new Term("field", "old")); expectedBuilder.add(new Term[] {new Term("field", "dogs"), new Term("field", "dog")}); QueryBuilder builder = new QueryBuilder(new MockSynonymAnalyzer()); assertEquals(expectedBuilder.build(), builder.createPhraseQuery("field", "old dogs")); }
/** forms multiphrase query */ public void testCJKSynonymsPhrase() throws Exception { MultiPhraseQuery.Builder expectedBuilder = new MultiPhraseQuery.Builder(); expectedBuilder.add(new Term("field", "中")); expectedBuilder.add(new Term[] {new Term("field", "国"), new Term("field", "國")}); QueryBuilder builder = new QueryBuilder(new MockCJKSynonymAnalyzer()); assertEquals(expectedBuilder.build(), builder.createPhraseQuery("field", "中国")); expectedBuilder.setSlop(3); assertEquals(expectedBuilder.build(), builder.createPhraseQuery("field", "中国", 3)); }
/** forms multiphrase query */ public void testCJKSynonymsPhrase() throws Exception { MultiPhraseQuery.Builder expectedQBuilder = new MultiPhraseQuery.Builder(); expectedQBuilder.add(new Term("field", "中")); expectedQBuilder.add(new Term[] {new Term("field", "国"), new Term("field", "國")}); QueryParser qp = new QueryParser("field", new MockCJKSynonymAnalyzer()); qp.setDefaultOperator(Operator.AND); assertEquals(expectedQBuilder.build(), qp.parse("\"中国\"")); Query expected = new BoostQuery(expectedQBuilder.build(), 2f); assertEquals(expected, qp.parse("\"中国\"^2")); expectedQBuilder.setSlop(3); expected = new BoostQuery(expectedQBuilder.build(), 2f); assertEquals(expected, qp.parse("\"中国\"~3^2")); }
/** forms multiphrase query */ public void testSynonymsPhrase() throws Exception { MultiPhraseQuery.Builder expectedQBuilder = new MultiPhraseQuery.Builder(); expectedQBuilder.add(new Term(FIELD, "old")); expectedQBuilder.add(new Term[] {new Term(FIELD, "dogs"), new Term(FIELD, "dog")}); QueryParser qp = new QueryParser(FIELD, new MockSynonymAnalyzer()); assertEquals(expectedQBuilder.build(), qp.parse("\"old dogs\"")); qp.setDefaultOperator(Operator.AND); assertEquals(expectedQBuilder.build(), qp.parse("\"old dogs\"")); BoostQuery expected = new BoostQuery(expectedQBuilder.build(), 2f); assertEquals(expected, qp.parse("\"old dogs\"^2")); expectedQBuilder.setSlop(3); expected = new BoostQuery(expectedQBuilder.build(), 2f); assertEquals(expected, qp.parse("\"old dogs\"~3^2")); }