in oak-solr-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/solr/query/FilterQueryParser.java [50:283]
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(" ");
}
}
if (plan != null && plan.getSortOrder() != null) {
List<QueryIndex.OrderEntry> sortOrder = plan.getSortOrder();
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);
continue; // sorting by relative properties not supported until index time aggregation is supported
}
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 (QueryConstants.REP_FACET.equals(pr.propertyName)) {
solrQuery.setFacetMinCount(1);
solrQuery.setFacet(true);
String value = pr.first.getValue(Type.STRING);
solrQuery.addFacetField(value.substring(QueryConstants.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(QueryConstants.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;
}