/** Removes toplevel ANDed simple words from the query. */ protected static FulltextQuery removeToplevelAndedWords(FulltextQuery ft) { if (ft.op == Op.OR || ft.op == Op.NOTWORD) { return ft; } if (ft.op == Op.WORD) { if (ft.isPhrase()) { return ft; } return null; } List<FulltextQuery> newTerms = new LinkedList<FulltextQuery>(); for (FulltextQuery term : ft.terms) { if (term.op == Op.NOTWORD) { newTerms.add(term); } else { // Op.WORD if (term.isPhrase()) { newTerms.add(term); } } } if (newTerms.isEmpty()) { return null; } else if (newTerms.size() == 1) { // single-term parenthesis elimination return newTerms.get(0); } else { FulltextQuery newFt = new FulltextQuery(); newFt.op = Op.AND; newFt.terms = newTerms; return newFt; } }
/** * Returns a fulltext query that is a superset of the original one and does not have phrase * searches. * * <p>Negative phrases (which are at AND level) are removed, positive phrases are split into ANDed * words. */ protected static FulltextQuery breakPhrases(FulltextQuery ft) { FulltextQuery newFt = new FulltextQuery(); if (ft.op == Op.AND || ft.op == Op.OR) { List<FulltextQuery> newTerms = new LinkedList<FulltextQuery>(); for (FulltextQuery term : ft.terms) { FulltextQuery broken = breakPhrases(term); if (broken == null) { // remove negative phrase } else if (ft.op == Op.AND && broken.op == Op.AND) { // associativity (sub-AND hoisting) newTerms.addAll(broken.terms); } else { newTerms.add(broken); } } if (newTerms.size() == 1) { // single-term parenthesis elimination newFt = newTerms.get(0); } else { newFt.op = ft.op; newFt.terms = newTerms; } } else { boolean isPhrase = ft.isPhrase(); if (!isPhrase) { newFt = ft; } else if (ft.op == Op.WORD) { // positive phrase // split it List<FulltextQuery> newTerms = new LinkedList<FulltextQuery>(); for (String subword : ft.word.split(" ")) { FulltextQuery sft = new FulltextQuery(); sft.op = Op.WORD; sft.word = subword; newTerms.add(sft); } newFt.op = Op.AND; newFt.terms = newTerms; } else { // negative phrase // removed newFt = null; } } return newFt; }