use of org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction in project jackrabbit-oak by apache.
the class ReferenceIndex method getPlan.
@Override
public String getPlan(Filter filter, NodeState root) {
StringBuilder buff = new StringBuilder("reference");
for (PropertyRestriction pr : filter.getPropertyRestrictions()) {
if (pr.propertyType == REFERENCE) {
buff.append(" PROPERTY([");
buff.append(pr.propertyName);
buff.append("], 'Reference') = ");
buff.append(pr.first.getValue(STRING));
return buff.toString();
}
if (pr.propertyType == WEAKREFERENCE) {
buff.append(" PROPERTY([");
buff.append(pr.propertyName);
buff.append("], 'WeakReference') = ");
buff.append(pr.first.getValue(STRING));
return buff.toString();
}
}
return buff.toString();
}
use of org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction in project jackrabbit-oak by apache.
the class LucenePropertyIndex method getLuceneRequest.
/**
* Get the Lucene query for the given filter.
*
* @param plan index plan containing filter details
* @param reader the Lucene reader
* @return the Lucene query
*/
private static LuceneRequestFacade getLuceneRequest(IndexPlan plan, IndexAugmentorFactory augmentorFactory, IndexReader reader) {
FulltextQueryTermsProvider augmentor = getIndexAgumentor(plan, augmentorFactory);
List<Query> qs = new ArrayList<Query>();
Filter filter = plan.getFilter();
FullTextExpression ft = filter.getFullTextConstraint();
PlanResult planResult = getPlanResult(plan);
IndexDefinition defn = planResult.indexDefinition;
Analyzer analyzer = defn.getAnalyzer();
if (ft == null) {
// there might be no full-text constraint
// when using the LowCostLuceneIndexProvider
// which is used for testing
} else {
qs.add(getFullTextQuery(plan, ft, analyzer, augmentor));
}
// Check if native function is supported
PropertyRestriction pr = null;
if (defn.hasFunctionDefined()) {
pr = filter.getPropertyRestriction(defn.getFunctionName());
}
if (pr != null) {
String query = String.valueOf(pr.first.getValue(pr.first.getType()));
QueryParser queryParser = new QueryParser(VERSION, "", analyzer);
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);
}
}
} else 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 (planResult.evaluateNonFullTextConstraints()) {
addNonFullTextConstraints(qs, plan, reader);
}
if (qs.size() == 0 && plan.getSortOrder() != null) {
// This case indicates that query just had order by and no
// property restriction defined. In this case property
// existence queries for each sort entry
List<OrderEntry> orders = removeNativeSort(plan.getSortOrder());
for (int i = 0; i < orders.size(); i++) {
OrderEntry oe = orders.get(i);
PropertyDefinition pd = planResult.getOrderedProperty(i);
PropertyRestriction orderRest = new PropertyRestriction();
orderRest.propertyName = oe.getPropertyName();
Query q = createQuery(oe.getPropertyName(), orderRest, pd);
if (q != null) {
qs.add(q);
}
}
}
if (qs.size() == 0) {
if (reader == null) {
// just return match all queries
return new LuceneRequestFacade<Query>(new MatchAllDocsQuery());
}
// be returned (if the index definition has a single rule)
if (planResult.evaluateNodeTypeRestriction()) {
return new LuceneRequestFacade<Query>(new MatchAllDocsQuery());
}
throw new IllegalStateException("No query created for filter " + filter);
}
return performAdditionalWraps(qs);
}
use of org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction in project jackrabbit-oak by apache.
the class IndexPlanner method getMaxPossibleNumDocs.
private int getMaxPossibleNumDocs(Map<String, PropertyDefinition> propDefns, Filter filter) {
IndexStatistics indexStatistics = indexNode.getIndexStatistics();
int minNumDocs = indexStatistics.numDocs();
for (Map.Entry<String, PropertyDefinition> propDef : propDefns.entrySet()) {
String key = propDef.getKey();
if (result.relPropMapping.containsKey(key)) {
key = getName(key);
}
int docCntForField = indexStatistics.getDocCountFor(key);
if (docCntForField == -1) {
continue;
}
int weight = propDef.getValue().weight;
PropertyRestriction pr = filter.getPropertyRestriction(key);
if (pr != null) {
if (pr.isNotNullRestriction()) {
// don't use weight for "is not null" restrictions
weight = 1;
} else {
if (weight > 1) {
// so assume we read at least 30%
if (!isEqualityRestriction(pr)) {
weight = Math.min(3, weight);
}
}
}
}
if (weight > 1) {
// use it to scale down the doc count - in broad strokes, we can think of weight
// as number of terms for the field with all terms getting equal share of
// the documents in this field
double scaledDocCnt = Math.ceil((double) docCntForField / weight);
if (minNumDocs < scaledDocCnt) {
continue;
}
// since, we've already taken care that scaled cost is lower than minCost,
// we can safely cast without risking overflow
minNumDocs = (int) scaledDocCnt;
} else if (docCntForField < minNumDocs) {
minNumDocs = docCntForField;
}
}
return minNumDocs;
}
use of org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction in project jackrabbit-oak by apache.
the class IndexPlanner method getPlanBuilder.
private IndexPlan.Builder getPlanBuilder() {
log.trace("Evaluating plan with index definition {}", definition);
if (wrongIndex()) {
return null;
}
FullTextExpression ft = filter.getFullTextConstraint();
if (!definition.getVersion().isAtLeast(IndexFormatVersion.V2)) {
log.trace("Index is old format. Not supported");
return null;
}
// Query Fulltext and Index does not support fulltext
if (ft != null && !definition.isFullTextEnabled()) {
return null;
}
IndexingRule indexingRule = getApplicableRule();
if (indexingRule == null) {
return null;
}
// Query Fulltext and indexing rule does not support fulltext
if (ft != null && !indexingRule.isFulltextEnabled()) {
return null;
}
if (!checkForQueryPaths()) {
log.trace("Opting out due mismatch between path restriction {} and query paths {}", filter.getPath(), definition.getQueryPaths());
return null;
}
result = new PlanResult(indexPath, definition, indexingRule);
if (definition.hasFunctionDefined() && filter.getPropertyRestriction(definition.getFunctionName()) != null) {
return getNativeFunctionPlanBuilder(indexingRule.getBaseNodeType());
}
List<String> indexedProps = newArrayListWithCapacity(filter.getPropertyRestrictions().size());
for (PropertyDefinition functionIndex : indexingRule.getFunctionRestrictions()) {
for (PropertyRestriction pr : filter.getPropertyRestrictions()) {
String f = functionIndex.function;
if (pr.propertyName.equals(f)) {
indexedProps.add(f);
result.propDefns.put(f, functionIndex);
}
}
}
// Optimization - Go further only if any of the property is configured
// for property index
List<String> facetFields = new LinkedList<String>();
boolean ntBaseRule = NT_BASE.equals(indexingRule.getNodeTypeName());
Map<String, PropertyDefinition> relativePropDefns = new HashMap<>();
if (indexingRule.propertyIndexEnabled) {
for (PropertyRestriction pr : filter.getPropertyRestrictions()) {
String name = pr.propertyName;
if (QueryConstants.RESTRICTION_LOCAL_NAME.equals(name)) {
continue;
}
if (name.startsWith(QueryConstants.FUNCTION_RESTRICTION_PREFIX)) {
// function-based indexes were handled before
continue;
}
if (QueryConstants.REP_FACET.equals(pr.propertyName)) {
String value = pr.first.getValue(Type.STRING);
facetFields.add(FacetHelper.parseFacetField(value));
}
PropertyDefinition pd = indexingRule.getConfig(pr.propertyName);
boolean relativeProps = false;
if (pd == null && ntBaseRule) {
// Direct match not possible. Check for relative property definition
// i.e. if no match found for jcr:content/@keyword then check if
// property definition exists for 'keyword'
pd = getSimpleProperty(indexingRule, pr.propertyName);
relativeProps = pd != null;
}
if (pd != null && pd.propertyIndexEnabled()) {
if (pr.isNullRestriction() && !pd.nullCheckEnabled) {
continue;
}
if (!matchesValuePattern(pr, pd)) {
continue;
}
// with some other definitions
if (pd.weight != 0 && !relativeProps) {
indexedProps.add(name);
}
if (relativeProps) {
relativePropDefns.put(name, pd);
} else {
result.propDefns.put(name, pd);
}
}
}
}
boolean evalNodeTypeRestrictions = canEvalNodeTypeRestrictions(indexingRule);
boolean evalPathRestrictions = canEvalPathRestrictions(indexingRule);
boolean canEvalAlFullText = canEvalAllFullText(indexingRule, ft);
boolean canEvalNodeNameRestriction = canEvalNodeNameRestriction(indexingRule);
if (ft != null && !canEvalAlFullText) {
return null;
}
if (indexedProps.isEmpty() && !relativePropDefns.isEmpty() && !canEvalAlFullText) {
indexedProps = planForRelativeProperties(relativePropDefns);
}
// Fulltext expression can also be like jcr:contains(jcr:content/metadata/@format, 'image')
List<OrderEntry> sortOrder = createSortOrder(indexingRule);
boolean canSort = canSortByProperty(sortOrder);
if (!indexedProps.isEmpty() || canSort || ft != null || evalPathRestrictions || evalNodeTypeRestrictions || canEvalNodeNameRestriction) {
int costPerEntryFactor = 1;
costPerEntryFactor += sortOrder.size();
IndexPlan.Builder plan = defaultPlan();
if (!sortOrder.isEmpty()) {
plan.setSortOrder(sortOrder);
}
if (facetFields.size() > 0) {
plan.setAttribute(FacetHelper.ATTR_FACET_FIELDS, facetFields);
}
if (ft == null) {
result.enableNonFullTextConstraints();
}
if (evalNodeTypeRestrictions) {
result.enableNodeTypeEvaluation();
}
if (canEvalNodeNameRestriction) {
result.enableNodeNameRestriction();
}
// Set a index based guess here. Unique would set its own value below
if (useActualEntryCount && !definition.isEntryCountDefined()) {
int maxPossibleNumDocs = getMaxPossibleNumDocs(result.propDefns, filter);
if (maxPossibleNumDocs >= 0) {
plan.setEstimatedEntryCount(maxPossibleNumDocs);
}
}
if (sortOrder.isEmpty() && ft == null) {
boolean uniqueIndexFound = planForSyncIndexes(indexingRule);
if (uniqueIndexFound) {
// For unique index there would be at max 1 entry
plan.setEstimatedEntryCount(1);
}
}
return plan.setCostPerEntry(definition.getCostPerEntry() / costPerEntryFactor);
}
return null;
}
use of org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction in project jackrabbit-oak by apache.
the class NodeTypeIndex method wrongIndex.
private static boolean wrongIndex(Filter filter) {
// skip index if "option(index ...)" doesn't match
PropertyRestriction indexName = filter.getPropertyRestriction(IndexConstants.INDEX_NAME_OPTION);
if (indexName != null && indexName.first != null) {
// index name specified: just verify this, and ignore tags
return !"nodetype".equals(indexName.first.getValue(Type.STRING));
}
PropertyRestriction indexTag = filter.getPropertyRestriction(IndexConstants.INDEX_TAG_OPTION);
// index tag specified (the nodetype index doesn't support tags)
return indexTag != null && indexTag.first != null;
}
Aggregations