Search in sources :

Example 6 with FullTextExpression

use of org.apache.jackrabbit.oak.spi.query.fulltext.FullTextExpression 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 7 with FullTextExpression

use of org.apache.jackrabbit.oak.spi.query.fulltext.FullTextExpression in project jackrabbit-oak by apache.

the class LuceneIndex method getPlans.

@Override
public List<IndexPlan> getPlans(Filter filter, List<OrderEntry> sortOrder, NodeState rootState) {
    FullTextExpression ft = filter.getFullTextConstraint();
    if (ft == null) {
        // as there might be a better one
        return Collections.emptyList();
    }
    String indexPath = new LuceneIndexLookup(rootState).getOldFullTextIndexPath(filter, tracker);
    if (indexPath == null) {
        // unusable index
        return Collections.emptyList();
    }
    Set<String> relPaths = getRelativePaths(ft);
    if (relPaths.size() > 1) {
        LOG.warn("More than one relative parent for query " + filter.getQueryStatement());
        // "contains(a/x, 'hello') and contains(b/x, 'world')"
        return Collections.emptyList();
    }
    IndexNode node = tracker.acquireIndexNode(indexPath);
    try {
        if (node != null) {
            IndexDefinition defn = node.getDefinition();
            return Collections.singletonList(planBuilder(filter).setEstimatedEntryCount(defn.getFulltextEntryCount(node.getIndexStatistics().numDocs())).setCostPerExecution(defn.getCostPerExecution()).setCostPerEntry(defn.getCostPerEntry()).setAttribute(ATTR_INDEX_PATH, indexPath).build());
        }
        // No index node then no plan possible
        return Collections.emptyList();
    } finally {
        if (node != null) {
            node.release();
        }
    }
}
Also used : FullTextExpression(org.apache.jackrabbit.oak.spi.query.fulltext.FullTextExpression)

Example 8 with FullTextExpression

use of org.apache.jackrabbit.oak.spi.query.fulltext.FullTextExpression in project jackrabbit-oak by apache.

the class LMSEstimatorTest method testMultipleUpdates.

@Test
public void testMultipleUpdates() throws Exception {
    LMSEstimator lmsEstimator = new LMSEstimator();
    Filter filter = mock(Filter.class);
    FullTextExpression fte = new FullTextTerm("foo", "bar", false, false, "");
    when(filter.getFullTextConstraint()).thenReturn(fte);
    SolrDocumentList docs = new SolrDocumentList();
    lmsEstimator.update(filter, docs);
    long actualCount = 10;
    docs.setNumFound(actualCount);
    long estimate = lmsEstimator.estimate(filter);
    assertEquals(estimate, lmsEstimator.estimate(filter));
    long diff = actualCount - estimate;
    // update causes weights adjustment
    lmsEstimator.update(filter, docs);
    long estimate2 = lmsEstimator.estimate(filter);
    assertEquals(estimate2, lmsEstimator.estimate(filter));
    long diff2 = actualCount - estimate2;
    // new estimate is more accurate than previous one
    assertTrue(diff2 < diff);
    // update doesn't cause weight adjustments therefore estimates stays unchanged
    lmsEstimator.update(filter, docs);
    long estimate3 = lmsEstimator.estimate(filter);
    assertEquals(estimate3, lmsEstimator.estimate(filter));
    long diff3 = actualCount - estimate3;
    assertTrue(diff3 < diff2);
}
Also used : FullTextTerm(org.apache.jackrabbit.oak.spi.query.fulltext.FullTextTerm) Filter(org.apache.jackrabbit.oak.spi.query.Filter) FullTextExpression(org.apache.jackrabbit.oak.spi.query.fulltext.FullTextExpression) SolrDocumentList(org.apache.solr.common.SolrDocumentList) Test(org.junit.Test)

Example 9 with FullTextExpression

use of org.apache.jackrabbit.oak.spi.query.fulltext.FullTextExpression in project jackrabbit-oak by apache.

the class IndexPlannerTest method fullTextQuery_RelativePropertyPaths.

@Test
public void fullTextQuery_RelativePropertyPaths() throws Exception {
    NodeBuilder defn = newLucenePropertyIndexDefinition(builder, "test", of("foo", "bar"), "async");
    // Index all props and then perform fulltext
    defn = IndexDefinition.updateDefinition(defn.getNodeState().builder());
    NodeBuilder foob = getNode(defn, "indexRules/nt:base/properties/foo");
    foob.setProperty(LuceneIndexConstants.PROP_NAME, "foo");
    foob.setProperty(LuceneIndexConstants.PROP_ANALYZED, true);
    NodeBuilder barb = getNode(defn, "indexRules/nt:base/properties/bar");
    barb.setProperty(LuceneIndexConstants.PROP_NAME, "bar");
    barb.setProperty(LuceneIndexConstants.PROP_ANALYZED, true);
    // where contains('jcr:content/bar', 'mountain OR valley') and contains('jcr:content/foo', 'mountain OR valley')
    // above query can be evaluated by index which indexes foo and bar with restriction that both belong to same node
    // by displacing the query path to evaluate on contains('bar', ...) and filter out those parents which do not
    // have jcr:content as parent
    FullTextExpression fooExp = FullTextParser.parse("jcr:content/bar", "mountain OR valley");
    FullTextExpression barExp = FullTextParser.parse("jcr:content/foo", "mountain OR valley");
    FullTextExpression exp = new FullTextAnd(Arrays.asList(fooExp, barExp));
    IndexPlanner planner = createPlannerForFulltext(defn.getNodeState(), exp);
    // No plan for unindex property
    assertNotNull(planner.getPlan());
}
Also used : FullTextAnd(org.apache.jackrabbit.oak.spi.query.fulltext.FullTextAnd) FullTextExpression(org.apache.jackrabbit.oak.spi.query.fulltext.FullTextExpression) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) Test(org.junit.Test)

Example 10 with FullTextExpression

use of org.apache.jackrabbit.oak.spi.query.fulltext.FullTextExpression in project jackrabbit-oak by apache.

the class IndexPlannerTest method fullTextQuery_IndexAllProps.

@Test
public void fullTextQuery_IndexAllProps() throws Exception {
    NodeBuilder defn = newLucenePropertyIndexDefinition(builder, "test", of("allProps"), "async");
    // Index all props and then perform fulltext
    defn = IndexDefinition.updateDefinition(defn.getNodeState().builder());
    NodeBuilder foob = getNode(defn, "indexRules/nt:base/properties/allProps");
    foob.setProperty(LuceneIndexConstants.PROP_NAME, LuceneIndexConstants.REGEX_ALL_PROPS);
    foob.setProperty(LuceneIndexConstants.PROP_ANALYZED, true);
    foob.setProperty(LuceneIndexConstants.PROP_IS_REGEX, true);
    FullTextExpression exp = FullTextParser.parse("bar", "mountain OR valley");
    exp = new FullTextContains("bar", "mountain OR valley", exp);
    IndexPlanner planner = createPlannerForFulltext(defn.getNodeState(), exp);
    // No plan for unindex property
    assertNotNull(planner.getPlan());
}
Also used : FullTextContains(org.apache.jackrabbit.oak.spi.query.fulltext.FullTextContains) FullTextExpression(org.apache.jackrabbit.oak.spi.query.fulltext.FullTextExpression) NodeBuilder(org.apache.jackrabbit.oak.spi.state.NodeBuilder) Test(org.junit.Test)

Aggregations

FullTextExpression (org.apache.jackrabbit.oak.spi.query.fulltext.FullTextExpression)21 Filter (org.apache.jackrabbit.oak.spi.query.Filter)7 FullTextAnd (org.apache.jackrabbit.oak.spi.query.fulltext.FullTextAnd)6 FullTextContains (org.apache.jackrabbit.oak.spi.query.fulltext.FullTextContains)6 FullTextTerm (org.apache.jackrabbit.oak.spi.query.fulltext.FullTextTerm)5 BooleanQuery (org.apache.lucene.search.BooleanQuery)5 MatchAllDocsQuery (org.apache.lucene.search.MatchAllDocsQuery)5 PrefixQuery (org.apache.lucene.search.PrefixQuery)5 Query (org.apache.lucene.search.Query)5 TermQuery (org.apache.lucene.search.TermQuery)5 TermRangeQuery (org.apache.lucene.search.TermRangeQuery)5 WildcardQuery (org.apache.lucene.search.WildcardQuery)5 Test (org.junit.Test)5 PropertyRestriction (org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction)4 FullTextOr (org.apache.jackrabbit.oak.spi.query.fulltext.FullTextOr)4 FullTextVisitor (org.apache.jackrabbit.oak.spi.query.fulltext.FullTextVisitor)4 ArrayList (java.util.ArrayList)3 AtomicReference (java.util.concurrent.atomic.AtomicReference)3 NodeBuilder (org.apache.jackrabbit.oak.spi.state.NodeBuilder)3 PhraseQuery (org.apache.lucene.search.PhraseQuery)3