Search in sources :

Example 1 with OrderEntry

use of org.apache.jackrabbit.oak.spi.query.QueryIndex.OrderEntry in project jackrabbit-oak by apache.

the class QueryImpl method canSortByIndex.

private boolean canSortByIndex() {
    boolean canSortByIndex = false;
    // TODO add issue about order by optimization for multiple selectors
    if (orderings != null && selectors.size() == 1) {
        IndexPlan plan = selectors.get(0).getExecutionPlan().getIndexPlan();
        if (plan != null) {
            List<OrderEntry> list = plan.getSortOrder();
            if (list != null && list.size() == orderings.length) {
                canSortByIndex = true;
                for (int i = 0; i < list.size(); i++) {
                    OrderEntry e = list.get(i);
                    OrderingImpl o = orderings[i];
                    DynamicOperandImpl op = o.getOperand();
                    if (!(op instanceof PropertyValueImpl)) {
                        // ordered by a function: currently not supported
                        canSortByIndex = false;
                        break;
                    }
                    // we only have one selector, so no need to check that
                    // TODO support joins
                    String pn = ((PropertyValueImpl) op).getPropertyName();
                    if (!pn.equals(e.getPropertyName())) {
                        // ordered by another property
                        canSortByIndex = false;
                        break;
                    }
                    if (o.isDescending() != (e.getOrder() == Order.DESCENDING)) {
                        // ordered ascending versus descending
                        canSortByIndex = false;
                        break;
                    }
                }
            }
        }
    }
    return canSortByIndex;
}
Also used : DynamicOperandImpl(org.apache.jackrabbit.oak.query.ast.DynamicOperandImpl) OrderEntry(org.apache.jackrabbit.oak.spi.query.QueryIndex.OrderEntry) IndexPlan(org.apache.jackrabbit.oak.spi.query.QueryIndex.IndexPlan) OrderingImpl(org.apache.jackrabbit.oak.query.ast.OrderingImpl) PropertyValueImpl(org.apache.jackrabbit.oak.query.ast.PropertyValueImpl)

Example 2 with OrderEntry

use of org.apache.jackrabbit.oak.spi.query.QueryIndex.OrderEntry in project jackrabbit-oak by apache.

the class IndexPlannerTest method noApplicableRule.

@Test
public void noApplicableRule() throws Exception {
    NodeBuilder defn = newLucenePropertyIndexDefinition(builder, "test", of("foo"), "async");
    defn.setProperty(createProperty(IndexConstants.DECLARING_NODE_TYPES, of("nt:folder"), STRINGS));
    IndexNode node = createIndexNode(new IndexDefinition(root, defn.getNodeState(), "/foo"));
    FilterImpl filter = createFilter("nt:base");
    filter.restrictProperty("foo", Operator.EQUAL, PropertyValues.newString("bar"));
    IndexPlanner planner = new IndexPlanner(node, "/foo", filter, Collections.<OrderEntry>emptyList());
    assertNull(planner.getPlan());
    filter = createFilter("nt:folder");
    filter.restrictProperty("foo", Operator.EQUAL, PropertyValues.newString("bar"));
    planner = new IndexPlanner(node, "/foo", filter, Collections.<OrderEntry>emptyList());
    assertNotNull(planner.getPlan());
}
Also used : OrderEntry(org.apache.jackrabbit.oak.spi.query.QueryIndex.OrderEntry) FilterImpl(org.apache.jackrabbit.oak.query.index.FilterImpl) LuceneIndexHelper.newLucenePropertyIndexDefinition(org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper.newLucenePropertyIndexDefinition) LuceneIndexHelper.newLuceneIndexDefinition(org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper.newLuceneIndexDefinition) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) Test(org.junit.Test)

Example 3 with OrderEntry

use of org.apache.jackrabbit.oak.spi.query.QueryIndex.OrderEntry in project jackrabbit-oak by apache.

the class IndexPlannerTest method planForSortField.

@Test
public void planForSortField() throws Exception {
    NodeBuilder defn = newLucenePropertyIndexDefinition(builder, "test", of("foo"), "async");
    defn.setProperty(createProperty(ORDERED_PROP_NAMES, of("foo"), STRINGS));
    IndexNode node = createIndexNode(new IndexDefinition(root, defn.getNodeState(), "/foo"));
    IndexPlanner planner = new IndexPlanner(node, "/foo", createFilter("nt:base"), ImmutableList.of(new OrderEntry("foo", Type.LONG, OrderEntry.Order.ASCENDING)));
    assertNotNull(planner.getPlan());
    assertTrue(pr(planner.getPlan()).isUniquePathsRequired());
}
Also used : OrderEntry(org.apache.jackrabbit.oak.spi.query.QueryIndex.OrderEntry) LuceneIndexHelper.newLucenePropertyIndexDefinition(org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper.newLucenePropertyIndexDefinition) LuceneIndexHelper.newLuceneIndexDefinition(org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper.newLuceneIndexDefinition) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) Test(org.junit.Test)

Example 4 with OrderEntry

use of org.apache.jackrabbit.oak.spi.query.QueryIndex.OrderEntry 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 OrderEntry

use of org.apache.jackrabbit.oak.spi.query.QueryIndex.OrderEntry in project jackrabbit-oak by apache.

the class IndexPlannerTest method syncIndex_NotUsedWithSort.

@Test
public void syncIndex_NotUsedWithSort() throws Exception {
    IndexDefinitionBuilder defnb = new IndexDefinitionBuilder();
    defnb.indexRule("nt:base").property("foo").propertyIndex().sync();
    defnb.indexRule("nt:base").property("bar").propertyIndex().ordered();
    IndexDefinition defn = new IndexDefinition(root, defnb.build(), "/foo");
    IndexNode node = createIndexNode(defn, 100);
    FilterImpl filter = createFilter("nt:base");
    filter.restrictProperty("foo", Operator.EQUAL, PropertyValues.newString("bar"));
    IndexPlanner planner = new IndexPlanner(node, "/foo", filter, ImmutableList.of(new OrderEntry("bar", Type.LONG, OrderEntry.Order.ASCENDING)));
    QueryIndex.IndexPlan plan = planner.getPlan();
    assertNotNull(plan);
    assertEquals(documentsPerValue(100), plan.getEstimatedEntryCount());
    PropertyIndexResult hr = pr(plan).getPropertyIndexResult();
    assertNull(hr);
}
Also used : OrderEntry(org.apache.jackrabbit.oak.spi.query.QueryIndex.OrderEntry) FilterImpl(org.apache.jackrabbit.oak.query.index.FilterImpl) LuceneIndexHelper.newLucenePropertyIndexDefinition(org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper.newLucenePropertyIndexDefinition) LuceneIndexHelper.newLuceneIndexDefinition(org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper.newLuceneIndexDefinition) PropertyIndexResult(org.apache.jackrabbit.oak.plugins.index.lucene.IndexPlanner.PropertyIndexResult) IndexDefinitionBuilder(org.apache.jackrabbit.oak.plugins.index.lucene.util.IndexDefinitionBuilder) QueryIndex(org.apache.jackrabbit.oak.spi.query.QueryIndex) Test(org.junit.Test)

Aggregations

OrderEntry (org.apache.jackrabbit.oak.spi.query.QueryIndex.OrderEntry)17 LuceneIndexHelper.newLuceneIndexDefinition (org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper.newLuceneIndexDefinition)12 LuceneIndexHelper.newLucenePropertyIndexDefinition (org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper.newLucenePropertyIndexDefinition)12 Test (org.junit.Test)12 FilterImpl (org.apache.jackrabbit.oak.query.index.FilterImpl)8 IndexDefinitionBuilder (org.apache.jackrabbit.oak.plugins.index.lucene.util.IndexDefinitionBuilder)6 QueryIndex (org.apache.jackrabbit.oak.spi.query.QueryIndex)6 NodeBuilder (org.apache.jackrabbit.oak.spi.state.NodeBuilder)6 IndexPlan (org.apache.jackrabbit.oak.spi.query.QueryIndex.IndexPlan)3 PropertyIndexResult (org.apache.jackrabbit.oak.plugins.index.lucene.IndexPlanner.PropertyIndexResult)2 DynamicOperandImpl (org.apache.jackrabbit.oak.query.ast.DynamicOperandImpl)2 OrderingImpl (org.apache.jackrabbit.oak.query.ast.OrderingImpl)2 Lists.newArrayList (com.google.common.collect.Lists.newArrayList)1 Maps.newHashMap (com.google.common.collect.Maps.newHashMap)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 LinkedList (java.util.LinkedList)1 IndexingRule (org.apache.jackrabbit.oak.plugins.index.lucene.IndexDefinition.IndexingRule)1 PropertyValueImpl (org.apache.jackrabbit.oak.query.ast.PropertyValueImpl)1 TraversingIndex (org.apache.jackrabbit.oak.query.index.TraversingIndex)1