private List<Post> findPosts() { try { FullTextSession fullTextSession = getFullTextSession((Session) entityManager.getDelegate()); Builder builder = new Builder(); String[] fields = new String[] { "message.text", "topic.subject" }; MultiFieldQueryParser parser = new MultiFieldQueryParser(fields, new StandardAnalyzer()); builder.add(parser.parse(POST_TEXT), MUST); builder.add(new TermQuery(new Term("topic.forum.id", "0")), MUST); builder.add(new TermQuery(new Term("topic.forum.category.id", "0")), MUST); builder.add(new WildcardQuery(new Term("poster.userId", "root")), MUST); addPostTimeQuery(builder); FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(builder.build(), Post.class); fullTextQuery.setSort(getSort()); fullTextQuery.setFirstResult(0); fullTextQuery.setMaxResults(15); @SuppressWarnings("unchecked") List<Post> posts = fullTextQuery.list(); return posts; } catch (ParseException e) { logger.severe("error"); return null; } }
private Query buildKeywordsQuery(String keywords, Query trackFilter) { Builder builder = new BooleanQuery.Builder(); if ("*".equals(keywords)) { builder.add(new WildcardQuery(new Term(TrackField.KEYWORDS.name(), keywords)), BooleanClause.Occur.MUST); } else { // Split into whole words with the last word having // a wildcard '*' on the end for (StringTokenizer tokens = new StringTokenizer(keywords, " "); tokens.hasMoreTokens();) { String token = tokens.nextToken(); if (tokens.hasMoreElements()) { builder.add(new TermQuery(new Term(TrackField.KEYWORDS.name(), token)), BooleanClause.Occur.MUST); } else { builder.add(new WildcardQuery(new Term(TrackField.KEYWORDS.name(), (token + "*"))), BooleanClause.Occur.MUST); } } } if (trackFilter != null) { builder.add(trackFilter, BooleanClause.Occur.MUST); } return builder.build(); }
void addCommonConstraints(Builder indexQuery, Query query) { // BooleanQuery categoryQueries = new BooleanQuery(); Builder categoryQueriesBuilder = new BooleanQuery.Builder(); for (String category : query.getCategories()) { categoryQueriesBuilder.add(new TermQuery(new Term(Concept.CATEGORY, category)), Occur.SHOULD); } if (!query.getCategories().isEmpty()) { indexQuery.add(new BooleanClause(categoryQueriesBuilder.build(), Occur.MUST)); } // BooleanQuery prefixQueries = new BooleanQuery(); Builder prefixQueriesBuilder = new BooleanQuery.Builder(); for (String curie : query.getPrefixes()) { String prefix = curieUtil.getExpansion(curie); prefixQueriesBuilder.add(new WildcardQuery(new Term(CommonProperties.IRI, prefix + "*")), Occur.SHOULD); } if (!query.getPrefixes().isEmpty()) { indexQuery.add(new BooleanClause(prefixQueriesBuilder.build(), Occur.MUST)); } }
@SuppressWarnings("serial") @Test public void testFilterCaching() throws Throwable { for (int i=0; i<10; i++) { final int j = i; addDocument(lucene, "id:" + i, null, new HashMap<String, String>() {{put("field" + j, "value0");}}); } final Builder b = new BooleanQuery.Builder(); for (int i=0; i<100; i++) b.add(new TermQuery(new Term("field" + i, "value0")), Occur.SHOULD); final BooleanQuery query = b.build(); LuceneResponse response = lucene.executeQuery(new QueryData(), Arrays.asList(query), null, null, null, null); for (int i =0; i <10; i++) lucene.executeQuery(new QueryData(), Arrays.asList(query), null, null, null, null); LuceneResponse responseWithCaching = lucene.executeQuery(new QueryData(), Arrays.asList(query), null, null, null, null); assertTrue(responseWithCaching.queryTime < response.queryTime); }
private void addPostTimeQuery(Builder query) { Calendar calendar = getInstance(); Date endDate = calendar.getTime(); calendar.add(DATE, -1); Date startDate = calendar.getTime(); query.add(newLongRange("createDate", startDate.getTime(), endDate.getTime(), true, true), MUST); }
@Override public List<Concept> searchConcepts(Query query) { QueryParser parser = getQueryParser(); // BooleanQuery finalQuery = new BooleanQuery(); Builder finalQueryBuilder = new BooleanQuery.Builder(); try { if (query.isIncludeSynonyms() || query.isIncludeAbbreviations() || query.isIncludeAcronyms()) { // BooleanQuery subQuery = new BooleanQuery(); Builder subQueryBuilder = new BooleanQuery.Builder(); subQueryBuilder.add(LuceneUtils.getBoostedQuery(parser, query.getInput(), 10.0f), Occur.SHOULD); String escapedQuery = QueryParser.escape(query.getInput()); if (query.isIncludeSynonyms()) { subQueryBuilder.add(parser.parse(Concept.SYNONYM + ":" + escapedQuery), Occur.SHOULD); } if (query.isIncludeAbbreviations()) { subQueryBuilder.add(parser.parse(Concept.ABREVIATION + ":" + escapedQuery), Occur.SHOULD); } if (query.isIncludeAcronyms()) { subQueryBuilder.add(parser.parse(Concept.ACRONYM + ":" + escapedQuery), Occur.SHOULD); } finalQueryBuilder.add(subQueryBuilder.build(), Occur.MUST); } else { finalQueryBuilder.add(parser.parse(query.getInput()), Occur.MUST); } } catch (ParseException e) { logger.log(Level.WARNING, "Failed to parse query", e); } addCommonConstraints(finalQueryBuilder, query); IndexHits<Node> hits = null; BooleanQuery finalQuery = finalQueryBuilder.build(); try (Transaction tx = graph.beginTx()) { hits = graph.index().getNodeAutoIndexer().getAutoIndex().query(finalQuery); tx.success(); } return limitHits(hits, query); }
/** * Creates a term filter for a set of terms. * @param terms some terms * @param mustMatchAll if true all terms must match ('AND' operation) * @return the filter */ static Query getTermsQuery(Map<String, ?> terms, boolean mustMatchAll) { BooleanQuery.Builder fb = new BooleanQuery.Builder(); int addedTerms = 0; boolean noop = true; Query bfb = null; for (Map.Entry<String, ?> term : terms.entrySet()) { Object val = term.getValue(); if (!StringUtils.isBlank(term.getKey()) && val != null) { Matcher matcher = Pattern.compile(".*(<|>|<=|>=)$").matcher(term.getKey().trim()); bfb = new TermQuery(new Term(term.getKey(), val.toString())); if (matcher.matches() && val instanceof Number) { String key = term.getKey().replaceAll("[<>=\\s]+$", ""); if (">".equals(matcher.group(1))) { bfb = TermRangeQuery.newStringRange(key, val.toString(), null, false, false); } else if ("<".equals(matcher.group(1))) { bfb = TermRangeQuery.newStringRange(key, null, val.toString(), false, false); } else if (">=".equals(matcher.group(1))) { bfb = TermRangeQuery.newStringRange(key, val.toString(), null, true, false); } else if ("<=".equals(matcher.group(1))) { bfb = TermRangeQuery.newStringRange(key, null, val.toString(), false, true); } } if (mustMatchAll) { fb.add(bfb, BooleanClause.Occur.MUST); } else { fb.add(bfb, BooleanClause.Occur.SHOULD); } addedTerms++; noop = false; } } if (addedTerms == 1 && bfb != null) { return bfb; } return noop ? null : fb.build(); }
@Override public <P extends ParaObject> List<P> findByIds(String appid, List<String> ids) { if (ids == null || ids.isEmpty()) { return Collections.emptyList(); } BooleanQuery.Builder fb = new BooleanQuery.Builder(); for (String id : ids) { if (!StringUtils.isBlank(id)) { fb.add(new TermQuery(new Term(Config._ID, id)), BooleanClause.Occur.SHOULD); } } return searchQuery(dao, appid, null, fb.build(), new Pager(ids.size())); }
@Override public <P extends ParaObject> List<P> findTagged(String appid, String type, String[] tags, Pager... pager) { if (tags == null || tags.length == 0 || StringUtils.isBlank(appid)) { return Collections.emptyList(); } Builder query = new BooleanQuery.Builder(); //assuming clean & safe tags here for (String tag : tags) { query.add(new TermQuery(new Term(Config._TAGS, tag)), BooleanClause.Occur.MUST); } // The filter looks like this: ("tag1" OR "tag2" OR "tag3") AND "type" return searchQuery(dao, appid, type, query.build(), pager); }
@Override public Long getCount(String appid, String type, Map<String, ?> terms) { if (StringUtils.isBlank(appid) || terms == null || terms.isEmpty()) { return 0L; } Query query = getTermsQuery(terms, true); if (query != null && !StringUtils.isBlank(type)) { query = new BooleanQuery.Builder(). add(query, BooleanClause.Occur.MUST). add(new TermQuery(new Term(Config._TYPE, type)), BooleanClause.Occur.FILTER). build(); } return (long) count(appid, query); }
@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); }
@Override public List<Concept> getConceptsFromPrefix(Query query) { QueryParser parser = getQueryParser(); // BooleanQuery finalQuery = new BooleanQuery(); Builder finalQueryBuilder = new BooleanQuery.Builder(); try { // BooleanQuery subQuery = new BooleanQuery(); Builder subQueryBuilder = new BooleanQuery.Builder(); subQueryBuilder.add(parser.parse(formatQuery("%s%s:%s*", NodeProperties.LABEL, LuceneUtils.EXACT_SUFFIX, query.getInput())), Occur.SHOULD); Optional<String> fullUri = curieUtil.getIri(query.getInput()); if (fullUri.isPresent()) { subQueryBuilder.add( parser.parse(formatQuery("%s:%s*", NodeProperties.IRI, (fullUri.get()))), Occur.SHOULD); } if (query.isIncludeSynonyms()) { subQueryBuilder.add( parser.parse(formatQuery("%s%s:%s*", Concept.SYNONYM, LuceneUtils.EXACT_SUFFIX, query.getInput())), Occur.SHOULD); } if (query.isIncludeAbbreviations()) { subQueryBuilder.add(parser.parse(formatQuery("%s%s:%s*", Concept.ABREVIATION, LuceneUtils.EXACT_SUFFIX, query.getInput())), Occur.SHOULD); } if (query.isIncludeAcronyms()) { subQueryBuilder.add( parser.parse(formatQuery("%s%s:%s*", Concept.ACRONYM, LuceneUtils.EXACT_SUFFIX, query.getInput())), Occur.SHOULD); } finalQueryBuilder.add(subQueryBuilder.build(), Occur.MUST); } catch (ParseException e) { logger.log(Level.WARNING, "Failed to parse query", e); } addCommonConstraints(finalQueryBuilder, query); BooleanQuery finalQuery = finalQueryBuilder.build(); IndexHits<Node> hits = null; try (Transaction tx = graph.beginTx()) { hits = graph.index().getNodeAutoIndexer().getAutoIndex().query(finalQuery); tx.success(); } return limitHits(hits, query); }
@Override public List<Concept> getConceptsFromTerm(Query query) { QueryParser parser = getQueryParser(); // String exactQuery = String.format("\"\\^ %s $\"", query.getInput()); String exactQuery = String.format("\"\\^ %s $\"", query.getInput()); Builder finalQueryBuilder = new BooleanQuery.Builder(); try { if (query.isIncludeSynonyms() || query.isIncludeAbbreviations() || query.isIncludeAcronyms()) { Builder subQueryBuilder = new BooleanQuery.Builder(); // subQuery.add(LuceneUtils.getBoostedQuery(parser, exactQuery, 10.0f), Occur.SHOULD); subQueryBuilder.add(LuceneUtils.getBoostedQuery(parser, exactQuery, 10.0f), Occur.SHOULD); if (query.isIncludeSynonyms()) { // subQuery.add(parser.parse(Concept.SYNONYM + ":" + exactQuery), Occur.SHOULD); subQueryBuilder.add(parser.parse(Concept.SYNONYM + ":" + exactQuery), Occur.SHOULD); } if (query.isIncludeAbbreviations()) { // subQuery.add(parser.parse(Concept.ABREVIATION + ":" + exactQuery), Occur.SHOULD); subQueryBuilder.add(parser.parse(Concept.ABREVIATION + ":" + exactQuery), Occur.SHOULD); } if (query.isIncludeAcronyms()) { // subQuery.add(parser.parse(Concept.ACRONYM + ":" + exactQuery), Occur.SHOULD); subQueryBuilder.add(parser.parse(Concept.ACRONYM + ":" + exactQuery), Occur.SHOULD); } // finalQuery.add(subQuery, Occur.MUST); finalQueryBuilder.add(subQueryBuilder.build(), Occur.MUST); } else { // finalQuery.add(parser.parse(exactQuery), Occur.MUST); finalQueryBuilder.add(parser.parse(exactQuery), Occur.MUST); } } catch (ParseException e) { logger.log(Level.WARNING, "Failed to parse query", e); } addCommonConstraints(finalQueryBuilder, query); BooleanQuery finalQuery = finalQueryBuilder.build(); logger.finest(finalQuery.toString()); try (Transaction tx = graph.beginTx()) { IndexHits<Node> hits = graph.index().getNodeAutoIndexer().getAutoIndex().query(finalQuery); tx.success(); return limitHits(hits, query); } }
protected Optional<Query> getPhraseFieldQueries() { // sloppy phrase queries for proximity final List<FieldParams> allPhraseFields = bmaxquery.getAllPhraseFields(); if (!allPhraseFields.isEmpty()) { final List<BmaxTerm> bmaxTerms = bmaxquery.getTerms(); if (bmaxTerms.size() > 1) { // it's a phrase final List<CharSequence> terms = bmaxTerms.stream().map(BmaxTerm::getTerm).collect(Collectors.toList()); final List<Query> disjuncts = new LinkedList<>(); final QueryBuilder queryBuilder = new QueryBuilder(schema.getQueryAnalyzer()); // memoization of phrase shingles final Map<Integer, List<String>> shingles = new HashMap<>(2); // build phrase queries for the phrase query fields for (final FieldParams fieldParams : allPhraseFields) { final int phraseLength = fieldParams.getWordGrams(); final int slop = fieldParams.getSlop(); final String fieldname = fieldParams.getField(); // get/create field-independent bi-gram or tri-gram strings final List<String> shinglesN = shingles.computeIfAbsent(phraseLength, n -> buildNGrams(terms, n)); // map bi-gram/tri-gram strings to phrase queries final List<Query> nGramQueries = shinglesN.stream() .map(nGram -> queryBuilder.createPhraseQuery(fieldname, nGram, slop)) .filter(Objects::nonNull) .collect(Collectors.toList()); switch (nGramQueries.size()) { case 0: break; case 1: { disjuncts.add(withBoostFactor(nGramQueries.get(0), fieldParams.getBoost())); break; } default: // If we have > 1 n-gram phrase for this field, aggregate their scores using // a BooleanQuery with all clauses being optional final BooleanQuery.Builder builder = new BooleanQuery.Builder() .setMinimumNumberShouldMatch(1); for (final Query nGramQuery : nGramQueries) { builder.add(nGramQuery, BooleanClause.Occur.SHOULD); } disjuncts.add(withBoostFactor(builder.build(), fieldParams.getBoost())); } } switch (disjuncts.size()) { case 0: break; case 1: return Optional.of(disjuncts.get(0)); default : return Optional.of(new DisjunctionMaxQuery(disjuncts, bmaxquery.getPhraseBoostTieBreaker())); } } } return empty(); }
/** * Geopoint distance query. Finds objects located near a center point. * @param <P> object type * @param dao {@link DAO} * @param appid appid * @param type object type to search for * @param query a geopoint query * @param queryString query string for filtering results * @param pager a {@link Pager} * @return a list of ParaObjects */ public static <P extends ParaObject> List<P> searchGeoQuery(DAO dao, String appid, String type, Query query, String queryString, Pager... pager) { if (StringUtils.isBlank(type) || StringUtils.isBlank(appid)) { return Collections.emptyList(); } if (StringUtils.isBlank(queryString)) { queryString = "*"; } DirectoryReader ireader = null; try { Pager page = getPager(pager); ireader = getIndexReader(appid); if (ireader != null) { Document[] hits1 = searchQueryRaw(ireader, appid, Utils.type(Address.class), query, page); page.setLastKey(null); // will cause problems if not cleared if (hits1.length == 0) { return Collections.emptyList(); } if (type.equals(Utils.type(Address.class))) { return searchQuery(dao, appid, hits1, page); } // then searchQuery their parent objects ArrayList<String> parentids = new ArrayList<>(hits1.length); for (Document doc : hits1) { Address address = documentToParaObject(doc); if (address != null && !StringUtils.isBlank(address.getParentid())) { parentids.add(address.getParentid()); } } Builder qsPart = new BooleanQuery.Builder(); qsPart.add(qs(queryString, MultiFields.getIndexedFields(ireader)), BooleanClause.Occur.MUST); Builder filterIdsPart = new BooleanQuery.Builder(); for (String id : parentids) { filterIdsPart.add(new TermQuery(new Term(Config._ID, id)), BooleanClause.Occur.SHOULD); } qsPart.add(filterIdsPart.build(), BooleanClause.Occur.FILTER); Document[] hits2 = searchQueryRaw(ireader, appid, type, qsPart.build(), page); return searchQuery(dao, appid, hits2, page); } } catch (Exception e) { logger.error(null, e); } finally { closeIndexReader(ireader); } return Collections.emptyList(); }
/** * Search where we return if any of the given strings appear. * * Accepts wildcard in queries */ public SearchResult searchWildcard(OrderedMap<String, Set<String>> fieldNameToValues, boolean applyAllDeletes, IDocumentsVisitor visitor, Map<String, String> translateFields, String... fieldsToLoad) throws IOException { Builder booleanQueryBuilder = new BooleanQuery.Builder(); Set<Entry<String, Set<String>>> entrySet = fieldNameToValues.entrySet(); for (Entry<String, Set<String>> entry : entrySet) { Builder fieldQueryBuilder = new BooleanQuery.Builder(); String fieldName = entry.getKey(); if (translateFields != null) { String newFieldName = translateFields.get(fieldName); if (newFieldName != null) { fieldName = newFieldName; } } boolean allNegate = true; for (String s : entry.getValue()) { if (s.length() == 0) { throw new RuntimeException("Unable to create term for searching empty string."); } boolean negate = false; if (s.startsWith("!")) { // Negation if dealing with paths if (IFields.FIELDS_NEGATED_WITH_EXCLAMATION.contains(fieldName)) { s = s.substring(1); negate = true; } } if (s.length() == 0) { // Only a single '!' for the negate. continue; } if (s.indexOf('*') != -1 || s.indexOf('?') != -1) { if (StringUtils.containsOnlyWildCards(s)) { throw new RuntimeException("Unable to create term for searching only wildcards: " + s); } fieldQueryBuilder.add(new WildcardQuery(new Term(fieldName, s)), negate ? BooleanClause.Occur.MUST_NOT : BooleanClause.Occur.SHOULD); } else { fieldQueryBuilder.add(new TermQuery(new Term(fieldName, s)), negate ? BooleanClause.Occur.MUST_NOT : BooleanClause.Occur.SHOULD); } if (!negate) { allNegate = false; } } BooleanQuery transitiveQuery = fieldQueryBuilder.build(); if (transitiveQuery.clauses().size() != 0) { if (allNegate) { // If all are negations, we actually have to add one which would // match all to remove the negations. fieldQueryBuilder.add(new MatchAllDocsQuery(), BooleanClause.Occur.SHOULD); } booleanQueryBuilder.add(fieldQueryBuilder.build(), BooleanClause.Occur.MUST); } } BooleanQuery booleanQuery = booleanQueryBuilder.build(); if (DEBUG) { System.out.println("Searching: " + booleanQuery); } return search(booleanQuery, applyAllDeletes, visitor, fieldsToLoad); }