use of org.apache.jackrabbit.oak.query.fulltext.FullTextExpression in project jackrabbit-oak by apache.
the class LuceneIndex method query.
@Override
public Cursor query(final IndexPlan plan, NodeState rootState) {
final Filter filter = plan.getFilter();
FullTextExpression ft = filter.getFullTextConstraint();
final Set<String> relPaths = getRelativePaths(ft);
if (relPaths.size() > 1) {
return new MultiLuceneIndex(filter, rootState, relPaths).query();
}
final String parent = relPaths.size() == 0 ? "" : relPaths.iterator().next();
// we only restrict non-full-text conditions if there is
// no relative property in the full-text constraint
final boolean nonFullTextConstraints = parent.isEmpty();
final int parentDepth = getDepth(parent);
QueryEngineSettings settings = filter.getQueryEngineSettings();
Iterator<LuceneResultRow> itr = new AbstractIterator<LuceneResultRow>() {
private final Deque<LuceneResultRow> queue = Queues.newArrayDeque();
private final Set<String> seenPaths = Sets.newHashSet();
private ScoreDoc lastDoc;
private int nextBatchSize = LUCENE_QUERY_BATCH_SIZE;
private boolean noDocs = false;
private long lastSearchIndexerVersion;
private int reloadCount;
@Override
protected LuceneResultRow computeNext() {
while (!queue.isEmpty() || loadDocs()) {
return queue.remove();
}
return endOfData();
}
private LuceneResultRow convertToRow(ScoreDoc doc, IndexSearcher searcher, String excerpt) throws IOException {
IndexReader reader = searcher.getIndexReader();
PathStoredFieldVisitor visitor = new PathStoredFieldVisitor();
reader.document(doc.doc, visitor);
String path = visitor.getPath();
if (path != null) {
if ("".equals(path)) {
path = "/";
}
if (!parent.isEmpty()) {
// TODO OAK-828 this breaks node aggregation
// get the base path
// ensure the path ends with the given
// relative path
// if (!path.endsWith("/" + parent)) {
// continue;
// }
path = getAncestorPath(path, parentDepth);
// avoid duplicate entries
if (seenPaths.contains(path)) {
return null;
}
seenPaths.add(path);
}
return new LuceneResultRow(path, doc.score, excerpt);
}
return null;
}
/**
* Loads the lucene documents in batches
* @return true if any document is loaded
*/
private boolean loadDocs() {
if (noDocs) {
return false;
}
ScoreDoc lastDocToRecord = null;
IndexNode indexNode = tracker.acquireIndexNode((String) plan.getAttribute(ATTR_INDEX_PATH));
checkState(indexNode != null);
try {
IndexSearcher searcher = indexNode.getSearcher();
LuceneRequestFacade luceneRequestFacade = getLuceneRequest(filter, searcher.getIndexReader(), nonFullTextConstraints, indexNode.getDefinition());
if (luceneRequestFacade.getLuceneRequest() instanceof Query) {
Query query = (Query) luceneRequestFacade.getLuceneRequest();
TopDocs docs;
long time = System.currentTimeMillis();
checkForIndexVersionChange(searcher);
while (true) {
if (lastDoc != null) {
LOG.debug("loading the next {} entries for query {}", nextBatchSize, query);
docs = searcher.searchAfter(lastDoc, query, nextBatchSize);
} else {
LOG.debug("loading the first {} entries for query {}", nextBatchSize, query);
docs = searcher.search(query, nextBatchSize);
}
time = System.currentTimeMillis() - time;
LOG.debug("... took {} ms", time);
nextBatchSize = (int) Math.min(nextBatchSize * 2L, 100000);
PropertyRestriction restriction = filter.getPropertyRestriction(QueryImpl.REP_EXCERPT);
boolean addExcerpt = restriction != null && restriction.isNotNullRestriction();
Analyzer analyzer = indexNode.getDefinition().getAnalyzer();
if (addExcerpt) {
// setup highlighter
QueryScorer scorer = new QueryScorer(query);
scorer.setExpandMultiTermQuery(true);
highlighter.setFragmentScorer(scorer);
}
for (ScoreDoc doc : docs.scoreDocs) {
String excerpt = null;
if (addExcerpt) {
excerpt = getExcerpt(analyzer, searcher, doc);
}
LuceneResultRow row = convertToRow(doc, searcher, excerpt);
if (row != null) {
queue.add(row);
}
lastDocToRecord = doc;
}
if (queue.isEmpty() && docs.scoreDocs.length > 0) {
lastDoc = lastDocToRecord;
} else {
break;
}
}
} else if (luceneRequestFacade.getLuceneRequest() instanceof SpellcheckHelper.SpellcheckQuery) {
SpellcheckHelper.SpellcheckQuery spellcheckQuery = (SpellcheckHelper.SpellcheckQuery) luceneRequestFacade.getLuceneRequest();
noDocs = true;
SuggestWord[] suggestWords = SpellcheckHelper.getSpellcheck(spellcheckQuery);
// ACL filter spellchecks
Collection<String> suggestedWords = new ArrayList<String>(suggestWords.length);
QueryParser qp = new QueryParser(Version.LUCENE_47, FieldNames.SUGGEST, indexNode.getDefinition().getAnalyzer());
for (SuggestWord suggestion : suggestWords) {
Query query = qp.createPhraseQuery(FieldNames.SUGGEST, suggestion.string);
TopDocs topDocs = searcher.search(query, 100);
if (topDocs.totalHits > 0) {
for (ScoreDoc doc : topDocs.scoreDocs) {
Document retrievedDoc = searcher.doc(doc.doc);
if (filter.isAccessible(retrievedDoc.get(FieldNames.PATH))) {
suggestedWords.add(suggestion.string);
break;
}
}
}
}
queue.add(new LuceneResultRow(suggestedWords));
} else if (luceneRequestFacade.getLuceneRequest() instanceof SuggestHelper.SuggestQuery) {
SuggestHelper.SuggestQuery suggestQuery = (SuggestHelper.SuggestQuery) luceneRequestFacade.getLuceneRequest();
noDocs = true;
List<Lookup.LookupResult> lookupResults = SuggestHelper.getSuggestions(indexNode.getLookup(), suggestQuery);
// ACL filter suggestions
Collection<String> suggestedWords = new ArrayList<String>(lookupResults.size());
QueryParser qp = new QueryParser(Version.LUCENE_47, FieldNames.FULLTEXT, indexNode.getDefinition().getAnalyzer());
for (Lookup.LookupResult suggestion : lookupResults) {
Query query = qp.createPhraseQuery(FieldNames.FULLTEXT, suggestion.key.toString());
TopDocs topDocs = searcher.search(query, 100);
if (topDocs.totalHits > 0) {
for (ScoreDoc doc : topDocs.scoreDocs) {
Document retrievedDoc = searcher.doc(doc.doc);
if (filter.isAccessible(retrievedDoc.get(FieldNames.PATH))) {
suggestedWords.add("{term=" + suggestion.key + ",weight=" + suggestion.value + "}");
break;
}
}
}
}
queue.add(new LuceneResultRow(suggestedWords));
}
} catch (IOException e) {
LOG.warn("query via {} failed.", LuceneIndex.this, e);
} finally {
indexNode.release();
}
if (lastDocToRecord != null) {
this.lastDoc = lastDocToRecord;
}
return !queue.isEmpty();
}
private void checkForIndexVersionChange(IndexSearcher searcher) {
long currentVersion = LucenePropertyIndex.getVersion(searcher);
if (currentVersion != lastSearchIndexerVersion && lastDoc != null) {
reloadCount++;
if (reloadCount > MAX_RELOAD_COUNT) {
LOG.error("More than {} index version changes detected for query {}", MAX_RELOAD_COUNT, plan);
throw new IllegalStateException("Too many version changes");
}
lastDoc = null;
LOG.debug("Change in index version detected {} => {}. Query would be performed without " + "offset; reload {}", currentVersion, lastSearchIndexerVersion, reloadCount);
}
this.lastSearchIndexerVersion = currentVersion;
}
};
SizeEstimator sizeEstimator = new SizeEstimator() {
@Override
public long getSize() {
IndexNode indexNode = tracker.acquireIndexNode((String) plan.getAttribute(ATTR_INDEX_PATH));
checkState(indexNode != null);
try {
IndexSearcher searcher = indexNode.getSearcher();
LuceneRequestFacade luceneRequestFacade = getLuceneRequest(filter, searcher.getIndexReader(), nonFullTextConstraints, indexNode.getDefinition());
if (luceneRequestFacade.getLuceneRequest() instanceof Query) {
Query query = (Query) luceneRequestFacade.getLuceneRequest();
TotalHitCountCollector collector = new TotalHitCountCollector();
searcher.search(query, collector);
int totalHits = collector.getTotalHits();
LOG.debug("Estimated size for query {} is {}", query, totalHits);
return totalHits;
}
LOG.debug("Estimated size: not a Query: {}", luceneRequestFacade.getLuceneRequest());
} catch (IOException e) {
LOG.warn("query via {} failed.", LuceneIndex.this, e);
} finally {
indexNode.release();
}
return -1;
}
};
return new LucenePathCursor(itr, settings, sizeEstimator);
}
use of org.apache.jackrabbit.oak.query.fulltext.FullTextExpression in project jackrabbit-oak by apache.
the class LuceneIndex method getFullTextQuery.
static Query getFullTextQuery(FullTextExpression ft, final Analyzer analyzer, final IndexReader reader) {
// a reference to the query, so it can be set in the visitor
// (a "non-local return")
final AtomicReference<Query> result = new AtomicReference<Query>();
ft.accept(new FullTextVisitor() {
@Override
public boolean visit(FullTextContains contains) {
return contains.getBase().accept(this);
}
@Override
public boolean visit(FullTextOr or) {
BooleanQuery q = new BooleanQuery();
for (FullTextExpression e : or.list) {
Query x = getFullTextQuery(e, analyzer, reader);
q.add(x, SHOULD);
}
result.set(q);
return true;
}
@Override
public boolean visit(FullTextAnd and) {
BooleanQuery q = new BooleanQuery();
for (FullTextExpression e : and.list) {
Query x = getFullTextQuery(e, analyzer, reader);
/* Only unwrap the clause if MUST_NOT(x) */
boolean hasMustNot = false;
if (x instanceof BooleanQuery) {
BooleanQuery bq = (BooleanQuery) x;
if ((bq.getClauses().length == 1) && (bq.getClauses()[0].getOccur() == BooleanClause.Occur.MUST_NOT)) {
hasMustNot = true;
q.add(bq.getClauses()[0]);
}
}
if (!hasMustNot) {
q.add(x, MUST);
}
}
result.set(q);
return true;
}
@Override
public boolean visit(FullTextTerm term) {
return visitTerm(term.getPropertyName(), term.getText(), term.getBoost(), term.isNot());
}
private boolean visitTerm(String propertyName, String text, String boost, boolean not) {
String p = propertyName;
if (p != null && p.indexOf('/') >= 0) {
p = getName(p);
}
Query q = tokenToQuery(text, p, analyzer, reader);
if (q == null) {
return false;
}
if (boost != null) {
q.setBoost(Float.parseFloat(boost));
}
if (not) {
BooleanQuery bq = new BooleanQuery();
bq.add(q, MUST_NOT);
result.set(bq);
} else {
result.set(q);
}
return true;
}
});
return result.get();
}
use of org.apache.jackrabbit.oak.query.fulltext.FullTextExpression in project jackrabbit-oak by apache.
the class LuceneIndex method getLuceneRequest.
/**
* Get the Lucene query for the given filter.
*
* @param filter the filter, including full-text constraint
* @param reader the Lucene reader
* @param nonFullTextConstraints whether non-full-text constraints (such a
* path, node type, and so on) should be added to the Lucene
* query
* @param indexDefinition nodestate that contains the index definition
* @return the Lucene query
*/
private static LuceneRequestFacade getLuceneRequest(Filter filter, IndexReader reader, boolean nonFullTextConstraints, IndexDefinition indexDefinition) {
List<Query> qs = new ArrayList<Query>();
Analyzer analyzer = indexDefinition.getAnalyzer();
FullTextExpression ft = filter.getFullTextConstraint();
if (ft == null) {
// there might be no full-text constraint
// when using the LowCostLuceneIndexProvider
// which is used for testing
} else {
qs.add(getFullTextQuery(ft, analyzer, reader));
}
PropertyRestriction pr = filter.getPropertyRestriction(NATIVE_QUERY_FUNCTION);
if (pr != null) {
String query = String.valueOf(pr.first.getValue(pr.first.getType()));
QueryParser queryParser = new QueryParser(VERSION, "", indexDefinition.getAnalyzer());
if (query.startsWith("mlt?")) {
String mltQueryString = query.replace("mlt?", "");
if (reader != null) {
Query moreLikeThis = MoreLikeThisHelper.getMoreLikeThis(reader, analyzer, mltQueryString);
if (moreLikeThis != null) {
qs.add(moreLikeThis);
}
}
}
if (query.startsWith("spellcheck?")) {
String spellcheckQueryString = query.replace("spellcheck?", "");
if (reader != null) {
return new LuceneRequestFacade<SpellcheckHelper.SpellcheckQuery>(SpellcheckHelper.getSpellcheckQuery(spellcheckQueryString, reader));
}
} else if (query.startsWith("suggest?")) {
String suggestQueryString = query.replace("suggest?", "");
if (reader != null) {
return new LuceneRequestFacade<SuggestHelper.SuggestQuery>(SuggestHelper.getSuggestQuery(suggestQueryString));
}
} else {
try {
qs.add(queryParser.parse(query));
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
} else if (nonFullTextConstraints) {
addNonFullTextConstraints(qs, filter, reader, analyzer, indexDefinition);
}
if (qs.size() == 0) {
return new LuceneRequestFacade<Query>(new MatchAllDocsQuery());
}
return LucenePropertyIndex.performAdditionalWraps(qs);
}
use of org.apache.jackrabbit.oak.query.fulltext.FullTextExpression in project jackrabbit-oak by apache.
the class FilterQueryParser method parseFullTextExpression.
private static String parseFullTextExpression(FullTextExpression ft, final OakSolrConfiguration configuration) {
final StringBuilder fullTextString = new StringBuilder();
ft.accept(new FullTextVisitor() {
@Override
public boolean visit(FullTextOr or) {
fullTextString.append('(');
for (int i = 0; i < or.list.size(); i++) {
if (i > 0 && i < or.list.size()) {
fullTextString.append(" OR ");
}
FullTextExpression e = or.list.get(i);
String orTerm = parseFullTextExpression(e, configuration);
fullTextString.append(orTerm);
}
fullTextString.append(')');
fullTextString.append(' ');
return true;
}
@Override
public boolean visit(FullTextContains contains) {
return contains.getBase().accept(this);
}
@Override
public boolean visit(FullTextAnd and) {
fullTextString.append('(');
for (int i = 0; i < and.list.size(); i++) {
if (i > 0 && i < and.list.size()) {
fullTextString.append(" AND ");
}
FullTextExpression e = and.list.get(i);
String andTerm = parseFullTextExpression(e, configuration);
fullTextString.append(andTerm);
}
fullTextString.append(')');
fullTextString.append(' ');
return true;
}
@Override
public boolean visit(FullTextTerm term) {
if (term.isNot()) {
fullTextString.append('-');
}
String p = term.getPropertyName();
if (p != null && p.indexOf('/') >= 0) {
p = getName(p);
}
if (p == null || "*".equals(p)) {
p = configuration.getCatchAllField();
}
fullTextString.append(partialEscape(p));
fullTextString.append(':');
String termText = term.getText();
if (termText.indexOf(' ') > 0) {
fullTextString.append('"');
}
fullTextString.append(termText.replace("/", "\\/").replace(":", "\\:"));
if (termText.indexOf(' ') > 0) {
fullTextString.append('"');
}
String boost = term.getBoost();
if (boost != null) {
fullTextString.append('^');
fullTextString.append(boost);
}
fullTextString.append(' ');
return true;
}
});
return fullTextString.toString();
}
use of org.apache.jackrabbit.oak.query.fulltext.FullTextExpression in project jackrabbit-oak by apache.
the class FilterQueryParser method getQuery.
static SolrQuery getQuery(Filter filter, QueryIndex.IndexPlan plan, OakSolrConfiguration configuration) {
SolrQuery solrQuery = new SolrQuery();
setDefaults(solrQuery, configuration);
StringBuilder queryBuilder = new StringBuilder();
FullTextExpression ft = filter.getFullTextConstraint();
if (ft != null) {
queryBuilder.append(parseFullTextExpression(ft, configuration));
queryBuilder.append(' ');
} else if (filter.getFulltextConditions() != null) {
Collection<String> fulltextConditions = filter.getFulltextConditions();
for (String fulltextCondition : fulltextConditions) {
queryBuilder.append(fulltextCondition).append(" ");
}
}
List<QueryIndex.OrderEntry> sortOrder = plan.getSortOrder();
if (sortOrder != null) {
for (QueryIndex.OrderEntry orderEntry : sortOrder) {
SolrQuery.ORDER order;
if (QueryIndex.OrderEntry.Order.ASCENDING.equals(orderEntry.getOrder())) {
order = SolrQuery.ORDER.asc;
} else {
order = SolrQuery.ORDER.desc;
}
String sortingField;
if (JcrConstants.JCR_PATH.equals(orderEntry.getPropertyName())) {
sortingField = partialEscape(configuration.getPathField()).toString();
} else if (JcrConstants.JCR_SCORE.equals(orderEntry.getPropertyName())) {
sortingField = "score";
} else {
if (orderEntry.getPropertyName().indexOf('/') >= 0) {
log.warn("cannot sort on relative properties, ignoring {} clause", orderEntry);
// sorting by relative properties not supported until index time aggregation is supported
continue;
}
sortingField = partialEscape(getSortingField(orderEntry.getPropertyType().tag(), orderEntry.getPropertyName())).toString();
}
solrQuery.addOrUpdateSort(sortingField, order);
}
}
Collection<Filter.PropertyRestriction> propertyRestrictions = filter.getPropertyRestrictions();
if (propertyRestrictions != null && !propertyRestrictions.isEmpty()) {
for (Filter.PropertyRestriction pr : propertyRestrictions) {
if (pr.isNullRestriction()) {
// can not use full "x is null"
continue;
}
// facets
if (QueryImpl.REP_FACET.equals(pr.propertyName)) {
solrQuery.setFacetMinCount(1);
solrQuery.setFacet(true);
String value = pr.first.getValue(Type.STRING);
solrQuery.addFacetField(value.substring(QueryImpl.REP_FACET.length() + 1, value.length() - 1) + "_facet");
}
// native query support
if (SolrQueryIndex.NATIVE_SOLR_QUERY.equals(pr.propertyName) || SolrQueryIndex.NATIVE_LUCENE_QUERY.equals(pr.propertyName)) {
String nativeQueryString = String.valueOf(pr.first.getValue(pr.first.getType()));
if (isSupportedHttpRequest(nativeQueryString)) {
// pass through the native HTTP Solr request
String requestHandlerString = nativeQueryString.substring(0, nativeQueryString.indexOf('?'));
if (!"select".equals(requestHandlerString)) {
if (requestHandlerString.charAt(0) != '/') {
requestHandlerString = "/" + requestHandlerString;
}
solrQuery.setRequestHandler(requestHandlerString);
}
String parameterString = nativeQueryString.substring(nativeQueryString.indexOf('?') + 1);
for (String param : parameterString.split("&")) {
String[] kv = param.split("=");
if (kv.length != 2) {
throw new RuntimeException("Unparsable native HTTP Solr query");
} else {
// more like this
if ("/mlt".equals(requestHandlerString)) {
if ("stream.body".equals(kv[0])) {
kv[0] = "q";
String mltFlString = "mlt.fl=";
int mltFlIndex = parameterString.indexOf(mltFlString);
if (mltFlIndex > -1) {
int beginIndex = mltFlIndex + mltFlString.length();
int endIndex = parameterString.indexOf('&', beginIndex);
String fields;
if (endIndex > beginIndex) {
fields = parameterString.substring(beginIndex, endIndex);
} else {
fields = parameterString.substring(beginIndex);
}
kv[1] = "_query_:\"{!dismax qf=" + fields + " q.op=OR}" + kv[1] + "\"";
}
}
if ("mlt.fl".equals(kv[0]) && ":path".equals(kv[1])) {
// rep:similar passes the path of the node to find similar documents for in the :path
// but needs its indexed content to find similar documents
kv[1] = configuration.getCatchAllField();
}
}
if ("/spellcheck".equals(requestHandlerString)) {
if ("term".equals(kv[0])) {
kv[0] = "spellcheck.q";
}
solrQuery.setParam("spellcheck", true);
}
if ("/suggest".equals(requestHandlerString)) {
if ("term".equals(kv[0])) {
kv[0] = "suggest.q";
}
solrQuery.setParam("suggest", true);
}
solrQuery.setParam(kv[0], kv[1]);
}
}
return solrQuery;
} else {
queryBuilder.append(nativeQueryString);
}
} else {
if (SolrQueryIndex.isIgnoredProperty(pr, configuration)) {
continue;
}
String first = null;
if (pr.first != null) {
first = partialEscape(String.valueOf(pr.first.getValue(pr.first.getType()))).toString();
}
String last = null;
if (pr.last != null) {
last = partialEscape(String.valueOf(pr.last.getValue(pr.last.getType()))).toString();
}
String prField = configuration.getFieldForPropertyRestriction(pr);
CharSequence fieldName = partialEscape(prField != null ? prField : pr.propertyName);
if ("jcr\\:path".equals(fieldName.toString())) {
queryBuilder.append(configuration.getPathField());
queryBuilder.append(':');
queryBuilder.append(first);
} else {
if (pr.first != null && pr.last != null && pr.first.equals(pr.last)) {
queryBuilder.append(fieldName).append(':');
queryBuilder.append(first);
} else if (pr.first == null && pr.last == null) {
if (!queryBuilder.toString().contains(fieldName + ":")) {
queryBuilder.append(fieldName).append(':');
queryBuilder.append('*');
}
} else if ((pr.first != null && pr.last == null) || (pr.last != null && pr.first == null) || (!pr.first.equals(pr.last))) {
// TODO : need to check if this works for all field types (most likely not!)
queryBuilder.append(fieldName).append(':');
queryBuilder.append(createRangeQuery(first, last, pr.firstIncluding, pr.lastIncluding));
} else if (pr.isLike) {
// TODO : the current parameter substitution is not expected to work well
queryBuilder.append(fieldName).append(':');
queryBuilder.append(partialEscape(String.valueOf(pr.first.getValue(pr.first.getType())).replace('%', '*').replace('_', '?')));
} else {
throw new RuntimeException("[unexpected!] not handled case");
}
}
}
queryBuilder.append(" ");
}
}
if (configuration.useForPrimaryTypes()) {
String[] pts = filter.getPrimaryTypes().toArray(new String[filter.getPrimaryTypes().size()]);
StringBuilder ptQueryBuilder = new StringBuilder();
for (int i = 0; i < pts.length; i++) {
String pt = pts[i];
if (i == 0) {
ptQueryBuilder.append("(");
}
if (i > 0 && i < pts.length) {
ptQueryBuilder.append("OR ");
}
ptQueryBuilder.append("jcr\\:primaryType").append(':').append(partialEscape(pt)).append(" ");
if (i == pts.length - 1) {
ptQueryBuilder.append(")");
ptQueryBuilder.append(' ');
}
}
solrQuery.addFilterQuery(ptQueryBuilder.toString());
}
if (filter.getQueryStatement() != null && filter.getQueryStatement().contains(QueryImpl.REP_EXCERPT)) {
if (!solrQuery.getHighlight()) {
// enable highlighting
solrQuery.setHighlight(true);
// defaults
solrQuery.set("hl.fl", "*");
solrQuery.set("hl.encoder", "html");
solrQuery.set("hl.mergeContiguous", true);
solrQuery.setHighlightSimplePre("<strong>");
solrQuery.setHighlightSimplePost("</strong>");
}
}
if (configuration.useForPathRestrictions()) {
Filter.PathRestriction pathRestriction = filter.getPathRestriction();
if (pathRestriction != null) {
String path = purgePath(filter, plan.getPathPrefix());
String fieldName = configuration.getFieldForPathRestriction(pathRestriction);
if (fieldName != null) {
if (pathRestriction.equals(Filter.PathRestriction.ALL_CHILDREN)) {
solrQuery.addFilterQuery(fieldName + ':' + path);
} else {
queryBuilder.append(fieldName);
queryBuilder.append(':');
queryBuilder.append(path);
}
}
}
}
if (configuration.collapseJcrContentNodes()) {
solrQuery.addFilterQuery("{!collapse field=" + configuration.getCollapsedPathField() + " min=" + configuration.getPathDepthField() + " hint=top_fc nullPolicy=expand}");
}
if (queryBuilder.length() == 0) {
queryBuilder.append("*:*");
}
String escapedQuery = queryBuilder.toString();
solrQuery.setQuery(escapedQuery);
if (log.isDebugEnabled()) {
log.debug("JCR query {} has been converted to Solr query {}", filter.getQueryStatement(), solrQuery.toString());
}
return solrQuery;
}
Aggregations