存储模型Overview
- 每一个图的点,边,shema,会被映射到 BackendEntity。
- BackEntity 以 HugeType + BackendColumn 来对数据建模
- 模型支持传统的 row based 的关系型数据库,也支持 cassendra 这样 column based 的数据库。
- 以addVertex 和 mysql 为例。Vertex 首先会被一个 serierlar 序列化 成 mysqlBackendEntity,对应一张数据库表的一个实体
- MysqlBackendStore 动态生成 sql,进行 save/update/delete。
serializer
在前面讲解 graphTransaction的时候提到了
*** this.doInsert(this.serializer.writeVertex(v)); ***
这个方法会调用对应存储引擎的serializer进行数据序列化。
我们看下 序列化的接口:
public interface GraphSerializer {
public BackendEntry writeVertex(HugeVertex vertex);
public BackendEntry writeVertexProperty(HugeVertexProperty<?> prop);
public HugeVertex readVertex(HugeGraph graph, BackendEntry entry);
public BackendEntry writeEdge(HugeEdge edge);
public BackendEntry writeEdgeProperty(HugeEdgeProperty<?> prop);
public HugeEdge readEdge(HugeGraph graph, BackendEntry entry);
public BackendEntry writeIndex(HugeIndex index);
public HugeIndex readIndex(HugeGraph graph, ConditionQuery query,
BackendEntry entry);
public BackendEntry writeId(HugeType type, Id id);
public Query writeQuery(Query query);
}
写的时候,将 图对象 转化成 backendEntity,读的时候将 backendEntity转化成图的对象。
顺藤摸瓜,看看 writeVertex 的实现。
writeVertex
@Override
public BackendEntry writeVertex(HugeVertex vertex) {
TableBackendEntry entry = newBackendEntry(vertex);
entry.column(HugeKeys.ID, IdUtil.writeString(vertex.id()));
entry.column(HugeKeys.LABEL, vertex.schemaLabel().id().asLong());
// Add all properties of a Vertex
this.formatProperties(vertex, entry.row());
return entry;
}
- 因为看的是mysql 的实现,所以它生成的是一个TableBackEntity,数据表的形式建模,
- TableBackendEntry 有几个重要元素,hugeType,ID,Row
- 可以看到一共是存入了三个column,Id,label,properties(formatProperties如下)
@Override
protected void formatProperties(HugeElement element,
TableBackendEntry.Row row) {
Map<Number, Object> properties = new HashMap<>();
// Add all properties of a Vertex
for (HugeProperty<?> prop : element.getProperties().values()) {
Number key = prop.propertyKey().id().asLong();
Object val = prop.value();
properties.put(key, val);
}
row.column(HugeKeys.PROPERTIES, JsonUtil.toJson(properties));
}
backEndStore.mutate()
在graphTransaction里面提交的时候,都使用了 backendStore的mutate方法,我们看看
mysql Backedn的mute方法
private void mutate(Session session, BackendAction item) {
MysqlBackendEntry entry = castBackendEntry(item.entry());
MysqlTable table = this.table(entry.type());
switch (item.action()) {
case INSERT:
table.insert(session, entry.row());
break;
case DELETE:
table.delete(session, entry.row());
break;
case APPEND:
table.append(session, entry.row());
break;
case ELIMINATE:
table.eliminate(session, entry.row());
break;
default:
throw new AssertionError(String.format(
"Unsupported mutate action: %s", item.action()));
}
}
这段代码,做了两件事
- 生成MysqlBackendEntity,这里很简单,实际就是做了类型转化。
- 获取操作 数据库的类是于 DAO 一样的类, 这里使用MysqlTable封装, 对于不同的类型,实现方式不一样,其实就是定义了一些schema
比如节点,table的schema 包含 ID,Label,Properties 等,整个hugegraph封装还是做的不错的。
接下来看看 insert方法
public void insert(Session session, MysqlBackendEntry.Row entry) {
String template = this.buildInsertTemplate(entry);
PreparedStatement insertStmt;
try {
// Create or get insert prepare statement
insertStmt = session.prepareStatement(template);
int i = 1;
for (Object object : entry.columns().values()) {
insertStmt.setObject(i++, object);
}
} catch (SQLException e) {
throw new BackendException("Failed to prepare statement '%s'" +
"for entry: %s", template, entry);
}
session.add(insertStmt);
}
- 根据 entry 动态构建 sql语句,并且根据columns的值设置 statement。
整个入库的过程就是这样,下面一张主要介绍,如何出库, 比如mysql 里面的数据是如何以图查询的。
网友评论