Search in sources :

Example 36 with IndexLabel

use of com.baidu.hugegraph.schema.IndexLabel in project incubator-hugegraph by apache.

the class GraphIndexTransaction method updateIndex.

/**
 * Update index(user properties) of vertex or edge
 * @param ilId      the id of index label
 * @param element   the properties owner
 * @param removed   remove or add index
 */
protected void updateIndex(Id ilId, HugeElement element, boolean removed) {
    SchemaTransaction schema = this.params().schemaTransaction();
    IndexLabel indexLabel = schema.getIndexLabel(ilId);
    E.checkArgument(indexLabel != null, "Not exist index label with id '%s'", ilId);
    // Collect property values of index fields
    List<Object> allPropValues = new ArrayList<>();
    int fieldsNum = indexLabel.indexFields().size();
    int firstNullField = fieldsNum;
    for (Id fieldId : indexLabel.indexFields()) {
        HugeProperty<Object> property = element.getProperty(fieldId);
        if (property == null) {
            E.checkState(hasNullableProp(element, fieldId), "Non-null property '%s' is null for '%s'", this.graph().propertyKey(fieldId), element);
            if (firstNullField == fieldsNum) {
                firstNullField = allPropValues.size();
            }
            allPropValues.add(ConditionQuery.INDEX_VALUE_NULL);
        } else {
            allPropValues.add(property.value());
        }
    }
    if (firstNullField == 0 && !indexLabel.indexType().isUnique()) {
        // The property value of first index field is null
        return;
    }
    // Not build index for record with nullable field (except unique index)
    List<Object> nnPropValues = allPropValues.subList(0, firstNullField);
    // Expired time
    long expiredTime = element.expiredTime();
    // Update index for each index type
    switch(indexLabel.indexType()) {
        case RANGE_INT:
        case RANGE_FLOAT:
        case RANGE_LONG:
        case RANGE_DOUBLE:
            E.checkState(nnPropValues.size() == 1, "Expect only one property in range index");
            Object value = NumericUtil.convertToNumber(nnPropValues.get(0));
            this.updateIndex(indexLabel, value, element.id(), expiredTime, removed);
            break;
        case SEARCH:
            E.checkState(nnPropValues.size() == 1, "Expect only one property in search index");
            value = nnPropValues.get(0);
            Set<String> words = this.segmentWords(propertyValueToString(value));
            for (String word : words) {
                this.updateIndex(indexLabel, word, element.id(), expiredTime, removed);
            }
            break;
        case SECONDARY:
            // Secondary index maybe include multi prefix index
            if (isCollectionIndex(nnPropValues)) {
                /*
                     * Property value is a collection
                     * we should create index for each item
                     */
                for (Object propValue : (Collection<?>) nnPropValues.get(0)) {
                    value = ConditionQuery.concatValues(propValue);
                    this.updateIndex(indexLabel, value, element.id(), expiredTime, removed);
                }
            } else {
                for (int i = 0, n = nnPropValues.size(); i < n; i++) {
                    List<Object> prefixValues = nnPropValues.subList(0, i + 1);
                    value = ConditionQuery.concatValues(prefixValues);
                    this.updateIndex(indexLabel, value, element.id(), expiredTime, removed);
                }
            }
            break;
        case SHARD:
            value = ConditionQuery.concatValues(nnPropValues);
            this.updateIndex(indexLabel, value, element.id(), expiredTime, removed);
            break;
        case UNIQUE:
            value = ConditionQuery.concatValues(allPropValues);
            assert !"".equals(value);
            Id id = element.id();
            // TODO: add lock for updating unique index
            if (!removed && this.existUniqueValue(indexLabel, value, id)) {
                throw new IllegalArgumentException(String.format("Unique constraint %s conflict is found for %s", indexLabel, element));
            }
            this.updateIndex(indexLabel, value, element.id(), expiredTime, removed);
            break;
        default:
            throw new AssertionError(String.format("Unknown index type '%s'", indexLabel.indexType()));
    }
}
Also used : IndexLabel(com.baidu.hugegraph.schema.IndexLabel) ArrayList(java.util.ArrayList) Collection(java.util.Collection) Id(com.baidu.hugegraph.backend.id.Id)

Example 37 with IndexLabel

use of com.baidu.hugegraph.schema.IndexLabel in project incubator-hugegraph by apache.

the class GraphIndexTransaction method collectMatchedIndex.

/**
 * Collect matched IndexLabel(s) in a SchemaLabel for a query
 * @param schemaLabel find indexLabels of this schemaLabel
 * @param query conditions container
 * @return MatchedLabel object contains schemaLabel and matched indexLabels
 */
@Watched(prefix = "index")
private MatchedIndex collectMatchedIndex(SchemaLabel schemaLabel, ConditionQuery query) {
    SchemaTransaction schema = this.params().schemaTransaction();
    Set<IndexLabel> ils = InsertionOrderUtil.newSet();
    for (Id il : schemaLabel.indexLabels()) {
        IndexLabel indexLabel = schema.getIndexLabel(il);
        /*
             * Method schema#getIndexLabel may return null here
             * because the indexLabel is being created at this time
             * and has not been saved to the backend storage
             */
        if (indexLabel == null || indexLabel.indexType().isUnique()) {
            continue;
        }
        ils.add(indexLabel);
    }
    if (this.graph().readMode().showOlap()) {
        for (IndexLabel il : schema.getIndexLabels()) {
            if (il.olap()) {
                ils.add(il);
            }
        }
    }
    if (ils.isEmpty()) {
        return null;
    }
    // Try to match single or composite index
    Set<IndexLabel> matchedILs = matchSingleOrCompositeIndex(query, ils);
    if (matchedILs.isEmpty()) {
        // Try to match joint indexes
        matchedILs = matchJointIndexes(query, ils);
    }
    if (!matchedILs.isEmpty()) {
        return new MatchedIndex(schemaLabel, matchedILs);
    }
    return null;
}
Also used : IndexLabel(com.baidu.hugegraph.schema.IndexLabel) Id(com.baidu.hugegraph.backend.id.Id) Watched(com.baidu.hugegraph.perf.PerfUtil.Watched)

Example 38 with IndexLabel

use of com.baidu.hugegraph.schema.IndexLabel in project incubator-hugegraph by apache.

the class GraphIndexTransaction method buildJointIndexesQueries.

private static IndexQueries buildJointIndexesQueries(ConditionQuery query, MatchedIndex index) {
    IndexQueries queries = IndexQueries.of(query);
    List<IndexLabel> allILs = new ArrayList<>(index.indexLabels());
    // Handle range/search indexes
    if (query.hasRangeCondition() || query.hasSearchCondition()) {
        Set<IndexLabel> matchedILs = matchRangeOrSearchIndexLabels(query, index.indexLabels());
        assert !matchedILs.isEmpty();
        allILs.removeAll(matchedILs);
        Set<Id> queryPropKeys = InsertionOrderUtil.newSet();
        for (IndexLabel il : matchedILs) {
            // Only one field each range/search index-label
            queryPropKeys.add(il.indexField());
        }
        // Construct queries by matched index-labels
        queries.putAll(constructQueries(query, matchedILs, queryPropKeys));
        // Remove matched queryPropKeys
        query = query.copy();
        for (Id field : queryPropKeys) {
            query.unsetCondition(field);
        }
        // Return if matched indexes satisfies query-conditions already
        if (query.userpropKeys().isEmpty()) {
            return queries;
        }
    }
    // Handle secondary joint indexes
    final ConditionQuery finalQuery = query;
    for (int i = 1, size = allILs.size(); i <= size; i++) {
        boolean found = cmn(allILs, size, i, 0, null, r -> {
            // All n indexLabels are selected, test current combination
            IndexQueries qs = constructJointSecondaryQueries(finalQuery, r);
            if (qs.isEmpty()) {
                return false;
            }
            queries.putAll(qs);
            return true;
        });
        if (found) {
            return queries;
        }
    }
    return IndexQueries.EMPTY;
}
Also used : ConditionQuery(com.baidu.hugegraph.backend.query.ConditionQuery) IndexLabel(com.baidu.hugegraph.schema.IndexLabel) ArrayList(java.util.ArrayList) Id(com.baidu.hugegraph.backend.id.Id)

Example 39 with IndexLabel

use of com.baidu.hugegraph.schema.IndexLabel in project incubator-hugegraph by apache.

the class GraphIndexTransaction method queryByLabel.

@Watched(prefix = "index")
private IdHolderList queryByLabel(ConditionQuery query) {
    HugeType queryType = query.resultType();
    IndexLabel il = IndexLabel.label(queryType);
    validateIndexLabel(il);
    Id label = query.condition(HugeKeys.LABEL);
    assert label != null;
    HugeType indexType;
    SchemaLabel schemaLabel;
    if (queryType.isVertex()) {
        indexType = HugeType.VERTEX_LABEL_INDEX;
        schemaLabel = this.graph().vertexLabel(label);
    } else if (queryType.isEdge()) {
        indexType = HugeType.EDGE_LABEL_INDEX;
        schemaLabel = this.graph().edgeLabel(label);
    } else {
        throw new HugeException("Can't query %s by label", queryType);
    }
    if (!this.store().features().supportsQueryByLabel() && !schemaLabel.enableLabelIndex()) {
        throw new NoIndexException("Don't accept query by label '%s', " + "label index is disabled", schemaLabel);
    }
    ConditionQuery indexQuery = new ConditionQuery(indexType, query);
    indexQuery.eq(HugeKeys.INDEX_LABEL_ID, il.id());
    indexQuery.eq(HugeKeys.FIELD_VALUES, label);
    /*
         * We can avoid redundant element ids if set limit, but if there are
         * label index overridden by other vertices with different label,
         * query with limit like g.V().hasLabel('xx').limit(10) may lose some
         * results, so can't set limit here. But in this case, the following
         * query results may be still different:
         *   g.V().hasLabel('xx').count()  // label index count
         *   g.V().hasLabel('xx').limit(-1).count()  // actual vertices count
         * It’s a similar situation for the offset, like:
         *   g.V().hasLabel('xx').range(26, 27)
         *   g.V().hasLabel('xx').range(27, 28)
         * we just reset limit here, but don't reset offset due to performance
         * optimization with index+offset query, see Query.skipOffsetIfNeeded().
         * NOTE: if set offset the backend itself will skip the offset
         */
    indexQuery.copyBasic(query);
    indexQuery.limit(Query.NO_LIMIT);
    IdHolder idHolder = this.doIndexQuery(il, indexQuery);
    IdHolderList holders = new IdHolderList(query.paging());
    holders.add(idHolder);
    return holders;
}
Also used : NoIndexException(com.baidu.hugegraph.exception.NoIndexException) SortByCountIdHolderList(com.baidu.hugegraph.backend.page.SortByCountIdHolderList) IdHolderList(com.baidu.hugegraph.backend.page.IdHolderList) ConditionQuery(com.baidu.hugegraph.backend.query.ConditionQuery) IndexLabel(com.baidu.hugegraph.schema.IndexLabel) IdHolder(com.baidu.hugegraph.backend.page.IdHolder) FixedIdHolder(com.baidu.hugegraph.backend.page.IdHolder.FixedIdHolder) PagingIdHolder(com.baidu.hugegraph.backend.page.IdHolder.PagingIdHolder) BatchIdHolder(com.baidu.hugegraph.backend.page.IdHolder.BatchIdHolder) SchemaLabel(com.baidu.hugegraph.schema.SchemaLabel) Id(com.baidu.hugegraph.backend.id.Id) HugeType(com.baidu.hugegraph.type.HugeType) HugeException(com.baidu.hugegraph.HugeException) Watched(com.baidu.hugegraph.perf.PerfUtil.Watched)

Example 40 with IndexLabel

use of com.baidu.hugegraph.schema.IndexLabel in project incubator-hugegraph by apache.

the class GraphIndexTransaction method relatedIndexLabels.

private static Set<IndexLabel> relatedIndexLabels(HugeElement element) {
    Set<IndexLabel> indexLabels = InsertionOrderUtil.newSet();
    Set<Id> indexLabelIds = element.schemaLabel().indexLabels();
    for (Id id : indexLabelIds) {
        IndexLabel indexLabel = element.graph().indexLabel(id);
        indexLabels.add(indexLabel);
    }
    return indexLabels;
}
Also used : IndexLabel(com.baidu.hugegraph.schema.IndexLabel) Id(com.baidu.hugegraph.backend.id.Id)

Aggregations

IndexLabel (com.baidu.hugegraph.schema.IndexLabel)53 Id (com.baidu.hugegraph.backend.id.Id)24 Watched (com.baidu.hugegraph.perf.PerfUtil.Watched)8 SchemaLabel (com.baidu.hugegraph.schema.SchemaLabel)8 SchemaManager (com.baidu.hugegraph.schema.SchemaManager)8 Test (org.junit.Test)8 ConditionQuery (com.baidu.hugegraph.backend.query.ConditionQuery)7 HugeGraph (com.baidu.hugegraph.HugeGraph)5 PropertyKey (com.baidu.hugegraph.schema.PropertyKey)5 HugeType (com.baidu.hugegraph.type.HugeType)5 GraphTransaction (com.baidu.hugegraph.backend.tx.GraphTransaction)4 SchemaTransaction (com.baidu.hugegraph.backend.tx.SchemaTransaction)4 VertexLabel (com.baidu.hugegraph.schema.VertexLabel)4 HugeIndex (com.baidu.hugegraph.structure.HugeIndex)4 LockUtil (com.baidu.hugegraph.util.LockUtil)4 IdHolder (com.baidu.hugegraph.backend.page.IdHolder)3 BatchIdHolder (com.baidu.hugegraph.backend.page.IdHolder.BatchIdHolder)3 FixedIdHolder (com.baidu.hugegraph.backend.page.IdHolder.FixedIdHolder)3 PagingIdHolder (com.baidu.hugegraph.backend.page.IdHolder.PagingIdHolder)3 Condition (com.baidu.hugegraph.backend.query.Condition)3