use of org.apache.jackrabbit.oak.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());
}
use of org.apache.jackrabbit.oak.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.getSearcher().getIndexReader().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();
}
}
}
use of org.apache.jackrabbit.oak.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);
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>();
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 (QueryImpl.REP_FACET.equals(pr.propertyName)) {
String value = pr.first.getValue(Type.STRING);
facetFields.add(FacetHelper.parseFacetField(value));
}
PropertyDefinition pd = indexingRule.getConfig(pr.propertyName);
if (pd != null && pd.propertyIndexEnabled()) {
if (pr.isNullRestriction() && !pd.nullCheckEnabled) {
continue;
}
indexedProps.add(name);
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;
}
//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) {
//TODO Need a way to have better cost estimate to indicate that
//this index can evaluate more propertyRestrictions natively (if more props are indexed)
//For now we reduce cost per entry
int costPerEntryFactor = indexedProps.size();
costPerEntryFactor += sortOrder.size();
//this index can evaluate more propertyRestrictions natively (if more props are indexed)
//For now we reduce cost per entry
IndexPlan.Builder plan = defaultPlan();
if (!sortOrder.isEmpty()) {
plan.setSortOrder(sortOrder);
}
if (costPerEntryFactor == 0) {
costPerEntryFactor = 1;
}
if (facetFields.size() > 0) {
plan.setAttribute(FacetHelper.ATTR_FACET_FIELDS, facetFields);
}
if (ft == null) {
result.enableNonFullTextConstraints();
}
if (evalNodeTypeRestrictions) {
result.enableNodeTypeEvaluation();
}
if (canEvalNodeNameRestriction) {
result.enableNodeNameRestriction();
}
return plan.setCostPerEntry(definition.getCostPerEntry() / costPerEntryFactor);
}
return null;
}
use of org.apache.jackrabbit.oak.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);
long diff = actualCount - estimate;
// update causes weights adjustment
lmsEstimator.update(filter, docs);
long 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, estimate2);
}
use of org.apache.jackrabbit.oak.query.fulltext.FullTextExpression in project jackrabbit-oak by apache.
the class LucenePropertyIndex method getPlanDescription.
@Override
public String getPlanDescription(IndexPlan plan, NodeState root) {
Filter filter = plan.getFilter();
IndexNode index = tracker.acquireIndexNode(getPlanResult(plan).indexPath);
checkState(index != null, "The Lucene index is not available");
try {
FullTextExpression ft = filter.getFullTextConstraint();
StringBuilder sb = new StringBuilder("lucene:");
String path = getPlanResult(plan).indexPath;
sb.append(getIndexName(plan)).append("(").append(path).append(") ");
sb.append(getLuceneRequest(plan, augmentorFactory, null));
if (plan.getSortOrder() != null && !plan.getSortOrder().isEmpty()) {
sb.append(" ordering:").append(plan.getSortOrder());
}
if (ft != null) {
sb.append(" ft:(").append(ft).append(")");
}
return sb.toString();
} finally {
index.release();
}
}
Aggregations