【JanusGraph】点数据操作源码解析

添加顶点与顶点属性操作流程图

顶点操作流程图

  1. 添加顶点源码解析
public abstract class JanusGraphBlueprintsTransaction implements JanusGraphTransaction {
     ......
     public JanusGraphVertex addVertex(Object... keyValues) {
        //校验传入参数
        ElementHelper.legalPropertyKeyValueArray(keyValues);
        
        if (ElementHelper.getIdValue(keyValues).isPresent() && !((StandardJanusGraph) getGraph()).getConfiguration().allowVertexIdSetting()) throw Vertex.Exceptions.userSuppliedIdsNotSupported();
        //解析并校验标签
        Object labelValue = null;
        for (int i = 0; i < keyValues.length; i = i + 2) {
            if (keyValues[i].equals(T.label)) {
                labelValue = keyValues[i+1];
                Preconditions.checkArgument(labelValue instanceof VertexLabel || labelValue instanceof String,
                        "Expected a string or VertexLabel as the vertex label argument, but got: %s",labelValue);
                if (labelValue instanceof String) ElementHelper.validateLabel((String) labelValue);
            }
        }
        //获取标签
        VertexLabel label = BaseVertexLabel.DEFAULT_VERTEXLABEL;
        if (labelValue!=null) {
            label = (labelValue instanceof VertexLabel)?(VertexLabel)labelValue:getOrCreateVertexLabel((String) labelValue);
        }
        
        //解析并获取顶点id
        final Long id = ElementHelper.getIdValue(keyValues).map(Number.class::cast).map(Number::longValue).orElse(null);
        final JanusGraphVertex vertex = addVertex(id, label);
        org.janusgraph.graphdb.util.ElementHelper.attachProperties(vertex, keyValues);
        return vertex;
    }
    ......
 }
public class BaseVertexLabel extends EmptyVertex implements InternalVertexLabel {
    //默认点标签
    String DEFAULT_LABEL = "vertex";
    public static final BaseVertexLabel DEFAULT_VERTEXLABEL = new BaseVertexLabel(Vertex.DEFAULT_LABEL);
    
    .....    
}
  1. 具体添加点操作,StandardJanusGraphTx
//StandardJanusGraphTx 实现类
public class StandardJanusGraphTx extends JanusGraphBlueprintsTransaction implements TypeInspector, SchemaInspector, VertexFactory {
    //添加点
    public JanusGraphVertex addVertex(Long vertexId, VertexLabel label) {
        //校验是否可修改,
        verifyWriteAccess();
        if (label==null) label=BaseVertexLabel.DEFAULT_VERTEXLABEL;
        if (vertexId != null && !graph.getConfiguration().allowVertexIdSetting()) {
            log.info("Provided vertex id [{}] is ignored because vertex id setting is not enabled", vertexId);
            vertexId = null;
        }
        //点id校验
        Preconditions.checkArgument(vertexId != null || !graph.getConfiguration().allowVertexIdSetting(), "Must provide vertex id");
        Preconditions.checkArgument(vertexId == null || IDManager.VertexIDType.NormalVertex.is(vertexId), "Not a valid vertex id: %s", vertexId);
        Preconditions.checkArgument(vertexId == null || ((InternalVertexLabel)label).hasDefaultConfiguration(), "Cannot only use default vertex labels: %s",label);
        Preconditions.checkArgument(vertexId == null || !config.hasVerifyExternalVertexExistence() || !containsVertex(vertexId), "Vertex with given id already exists: %s", vertexId);
        //获取id,并根据id和标签构建点对象
        StandardVertex vertex = new StandardVertex(this, IDManager.getTemporaryVertexID(IDManager.VertexIDType.NormalVertex, temporaryIds.nextID()), ElementLifeCycle.New);
        if (vertexId != null) {
            vertex.setId(vertexId);
        } else if (config.hasAssignIDsImmediately() || label.isPartitioned()) {
            graph.assignID(vertex,label);
        }
        //如果传入属性,则添加属性
        addProperty(vertex, BaseKey.VertexExists, Boolean.TRUE);
        // 如果点标签,不是默认标签,则添加一条VertexLable标签的边,
        // 记录顶点和标签的关系
        if (label!=BaseVertexLabel.DEFAULT_VERTEXLABEL) { //Add lable
            Preconditions.checkArgument(label instanceof VertexLabelVertex);
            addEdge(vertex, label, BaseLabel.VertexLabelEdge);
        }
        //将点添加到点缓存中,
        vertexCache.add(vertex, vertex.longId());
        return vertex;
    
    }
  1. 添加属性,以及属性操作方法;如果属性已经存在,在修改属性,如果属性不存在,则删除属性。
//添加属性
    /**
        VertexProperty.Cardinality cardinality 
        点属性基数类型:single,list,set
    */
    //添加属性
    /**
        VertexProperty.Cardinality cardinality 
        点属性基数类型:single,list,set
    */
    public JanusGraphVertexProperty addProperty(VertexProperty.Cardinality cardinality, JanusGraphVertex vertex, PropertyKey key, Object value, Long id) {
        //校验属性基数类型
        if (key.cardinality().convert()!=cardinality && cardinality!=VertexProperty.Cardinality.single)
            throw new SchemaViolationException("Key is defined for %s cardinality which conflicts with specified: %s",key.cardinality(),cardinality);
        //校验点是否可操作:(是否是只读)
        verifyWriteAccess(vertex);
        Preconditions.checkArgument(!(key instanceof ImplicitKey),"Cannot create a property of implicit type: %s",key.name());
        vertex = ((InternalVertex) vertex).it();
        Preconditions.checkNotNull(key);
        //校验属性key是否在点标签管理属性中,如果未关联
        //则将属性约束添加到给定的点标签中,即,将点标签与属性key,通过边关联
        //在图中,点标签,和属性key均是以点存储。
        //并且校验属性key是否在模型的点标签关联属性中。
        checkPropertyConstraintForVertexOrCreatePropertyConstraint(vertex, key);
        final Object normalizedValue = verifyAttribute(key, value);
        Cardinality keyCardinality = key.cardinality();

        //确定唯一索引,传入的属性key,是否是唯一索引
        final List<IndexLockTuple> uniqueIndexTuples = new ArrayList<>();
        for (CompositeIndexType index : TypeUtil.getUniqueIndexes(key)) {
            IndexSerializer.IndexRecords matches = IndexSerializer.indexMatches(vertex, index, key, normalizedValue);
            for (Object[] match : matches.getRecordValues()) uniqueIndexTuples.add(new IndexLockTuple(index,match));
        }

        TransactionLock uniqueLock = getUniquenessLock(vertex, (InternalRelationType) key, normalizedValue);
        //Add locks for unique indexes
        for (IndexLockTuple lockTuple : uniqueIndexTuples) uniqueLock = new CombinerLock(uniqueLock,getLock(lockTuple),times);
        uniqueLock.lock(LOCK_TIMEOUT);
        try {
            //获取点id,
            long propId = id == null ? IDManager.getTemporaryRelationID(temporaryIds.nextID()) : id;
           //获取属性对象
             StandardVertexProperty prop = new StandardVertexProperty(propId, key, (InternalVertex) vertex, normalizedValue, ElementLifeCycle.New);
            if (config.hasAssignIDsImmediately() && id == null) graph.assignID(prop);

            //Delete properties if the cardinality is restricted
            // 如果属性受限制,比如属性基数是:single或者set,
            // 则当传入key已经存在,则删除key,然后添加新值;
            if (cardinality==VertexProperty.Cardinality.single || cardinality== VertexProperty.Cardinality.set) {
                Consumer<JanusGraphVertexProperty> propertyRemover = JanusGraphVertexProperty.getRemover(cardinality, normalizedValue);
                /* If we are simply overwriting a vertex property, then we don't have to explicitly remove it thereby saving a read operation
                   However, this only applies if
                   1) we don't lock on the property key or consistency checks are disabled and
                   2) there are no indexes for this property key
                   3) the cardinalities match (if we overwrite a set with single, we need to read all other values to delete)
                */
                
               /* 如果我们只是覆盖顶点属性,那么我们不必显式删除它,从而节省了读取操作
                /*    然而,这仅适用于以下情况:
                 /*   1) 我们不锁定属性键,或者一致性检查被禁用
                 /*   2) 此属性键没有索引
                 /*  3) 基数匹配(如果我们用single覆盖一个集,我们需要读取所有其他要删除的值)
                */
                 if ( (!config.hasVerifyUniqueness() || ((InternalRelationType)key).getConsistencyModifier()!=ConsistencyModifier.LOCK) &&
                        !TypeUtil.hasAnyIndex(key) && cardinality==keyCardinality.convert()) {
                    //Only delete in-memory so as to not trigger a read from the database which isn't necessary because we will overwrite blindly
                    //We need to label the new property as "upsert", so that in case property deletion happens, we not only delete this new
                    //in-memory property, but also read from database to delete the old value (if exists)
                 
                    // 只在内存中删除,以免触发从数据库中读取不必要的内容,因为我们将盲目覆盖
                    // 我们需要将新属性标记为“upsert”,以便在发生属性删除时,我们不仅删除这个新的内存属性,
                    // 还从数据库中读取以删除旧值(如果存在)
                    
                    ((InternalVertex) vertex).getAddedRelations(p -> p.getType().equals(key)).forEach(p -> propertyRemover.accept((JanusGraphVertexProperty) p));
                    prop.setUpsert(true);
                } else {
                    ((InternalVertex) vertex).query().types(key).properties().forEach(propertyRemover);
                }
            }

            //Check index uniqueness
            if (config.hasVerifyUniqueness()) {
                //Check all unique indexes
                for (IndexLockTuple lockTuple : uniqueIndexTuples) {
                    if (!Iterables.isEmpty(IndexHelper.getQueryResults(lockTuple.getIndex(), lockTuple.getAll(), this)))
                        throw new SchemaViolationException("Adding this property for key [%s] and value [%s] violates a uniqueness constraint [%s]", key.name(), normalizedValue, lockTuple.getIndex());
                }
            }
            //关联属性
            connectRelation(prop);
            return prop;
        } finally {
            uniqueLock.unlock();
        }

    }

    }
}
  1. 调用DefaultSchemaMaker接口的makePropertyConstraintForVertex,对添加属性进行校验并且
    根据schema模型管理,给顶点标签添加属性key的约束(属性与顶点标签创建边)
public interface DefaultSchemaMaker {
        /**
     * Add property constraints for a given vertex label using the schema manager.
     *
     * @param vertexLabel to which the constraint applies.
     * @param key defines the property which should be added to the vertex label as a constraint.
     * @param manager is used to update the schema.
     * @see org.janusgraph.core.schema.SchemaManager
     */
    default void makePropertyConstraintForVertex(VertexLabel vertexLabel, PropertyKey key, SchemaManager manager) {
        manager.addProperties(vertexLabel, key);
    }
}

该类实现DefaultSchemaMaker ,并通过校验属性key是否在模型中


//备注:该类实现DefaultSchemaMaker ,并通过校验属性key是否在模型中
public class DisableDefaultSchemaMaker implements DefaultSchemaMaker {
    @Override
    public void makePropertyConstraintForVertex(VertexLabel vertexLabel, PropertyKey key, SchemaManager manager) {
        throw new IllegalArgumentException(
            String.format("Property Key constraint does not exist for given Vertex Label [%s] and property key [%s].", vertexLabel, key));
    }
}

将点属性key与点标签通过边关联,从而添加约束校验

//将点属性key与点标签通过边关联,从而添加约束校验
@Override
public VertexLabel addProperties(VertexLabel vertexLabel, PropertyKey... keys) {
    for (PropertyKey key : keys) {
        addSchemaEdge(vertexLabel, key, TypeDefinitionCategory.PROPERTY_KEY_EDGE, null);
    }
    return vertexLabel;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

stay_running

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值