protected void updateIndex()

in hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/tx/GraphIndexTransaction.java [213:315]


    protected void updateIndex(Id ilId, HugeElement element, boolean removed) {
        ISchemaTransaction 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()));
        }
    }