Search in sources :

Example 1 with PropertyRestriction

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();
}
Also used : PropertyRestriction(org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction)

Example 2 with PropertyRestriction

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);
}
Also used : PropertyRestriction(org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction) PlanResult(org.apache.jackrabbit.oak.plugins.index.lucene.IndexPlanner.PlanResult) Query(org.apache.lucene.search.Query) MatchAllDocsQuery(org.apache.lucene.search.MatchAllDocsQuery) WildcardQuery(org.apache.lucene.search.WildcardQuery) NumericRangeQuery(org.apache.lucene.search.NumericRangeQuery) CustomScoreQuery(org.apache.lucene.queries.CustomScoreQuery) PrefixQuery(org.apache.lucene.search.PrefixQuery) TermQuery(org.apache.lucene.search.TermQuery) BooleanQuery(org.apache.lucene.search.BooleanQuery) TermRangeQuery(org.apache.lucene.search.TermRangeQuery) SuggestHelper(org.apache.jackrabbit.oak.plugins.index.lucene.util.SuggestHelper) ArrayList(java.util.ArrayList) FulltextQueryTermsProvider(org.apache.jackrabbit.oak.plugins.index.lucene.spi.FulltextQueryTermsProvider) Analyzer(org.apache.lucene.analysis.Analyzer) MatchAllDocsQuery(org.apache.lucene.search.MatchAllDocsQuery) StandardQueryParser(org.apache.lucene.queryparser.flexible.standard.StandardQueryParser) QueryParser(org.apache.lucene.queryparser.classic.QueryParser) Filter(org.apache.jackrabbit.oak.spi.query.Filter) FullTextExpression(org.apache.jackrabbit.oak.spi.query.fulltext.FullTextExpression) ParseException(org.apache.lucene.queryparser.classic.ParseException)

Example 3 with PropertyRestriction

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;
}
Also used : PropertyRestriction(org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction) HashMap(java.util.HashMap) Map(java.util.Map) Maps.newHashMap(com.google.common.collect.Maps.newHashMap)

Example 4 with PropertyRestriction

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;
}
Also used : PropertyRestriction(org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction) HashMap(java.util.HashMap) Maps.newHashMap(com.google.common.collect.Maps.newHashMap) LinkedList(java.util.LinkedList) OrderEntry(org.apache.jackrabbit.oak.spi.query.QueryIndex.OrderEntry) IndexingRule(org.apache.jackrabbit.oak.plugins.index.lucene.IndexDefinition.IndexingRule) IndexPlan(org.apache.jackrabbit.oak.spi.query.QueryIndex.IndexPlan) FullTextExpression(org.apache.jackrabbit.oak.spi.query.fulltext.FullTextExpression)

Example 5 with PropertyRestriction

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;
}
Also used : PropertyRestriction(org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction)

Aggregations

PropertyRestriction (org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction)15 PrefixQuery (org.apache.lucene.search.PrefixQuery)6 TermQuery (org.apache.lucene.search.TermQuery)6 WildcardQuery (org.apache.lucene.search.WildcardQuery)6 BooleanQuery (org.apache.lucene.search.BooleanQuery)5 MatchAllDocsQuery (org.apache.lucene.search.MatchAllDocsQuery)5 Query (org.apache.lucene.search.Query)5 TermRangeQuery (org.apache.lucene.search.TermRangeQuery)5 ArrayList (java.util.ArrayList)4 Filter (org.apache.jackrabbit.oak.spi.query.Filter)4 FullTextExpression (org.apache.jackrabbit.oak.spi.query.fulltext.FullTextExpression)4 Analyzer (org.apache.lucene.analysis.Analyzer)4 QueryParser (org.apache.lucene.queryparser.classic.QueryParser)4 PlanResult (org.apache.jackrabbit.oak.plugins.index.lucene.IndexPlanner.PlanResult)3 SpellcheckHelper (org.apache.jackrabbit.oak.plugins.index.lucene.util.SpellcheckHelper)3 SuggestHelper (org.apache.jackrabbit.oak.plugins.index.lucene.util.SuggestHelper)3 CustomScoreQuery (org.apache.lucene.queries.CustomScoreQuery)3 ParseException (org.apache.lucene.queryparser.classic.ParseException)3 NumericRangeQuery (org.apache.lucene.search.NumericRangeQuery)3 AbstractIterator (com.google.common.collect.AbstractIterator)2