neo4j 底层存储结构分析(8)

  • Post author:
  • Post category:IT
  • Post comments:0评论

上一节:neo4j 底层存储结构分析(7)

3.8  示例1:neo4j_exam

下面看一个简单的例子,然后看一下几个主要的存储文件,有助于理解<3–neo4j存储结构>描述的neo4j 的存储格式。

3.8.1    neo4j_exm 代码

<div>

<b>package</b> com.wuzhu.neo4j_exam;

<b>import</b> java.util.List;

<b>import</b> java.util.ArrayList;

<b>import</b> java.util.Iterator;

<b>import</b> org.neo4j.graphdb.Direction;

<b>import</b> org.neo4j.graphdb.GraphDatabaseService;

<b>import</b> org.neo4j.graphdb.factory.GraphDatabaseFactory;

<b>import</b> org.neo4j.graphdb.Node;

<b>import</b> org.neo4j.graphdb.Relationship;

<b>import</b> org.neo4j.graphdb.Path;

<b>import</b> org.neo4j.graphdb.RelationshipType;

<b>import</b> org.neo4j.graphdb.Transaction;

<b>import</b> org.neo4j.graphdb.index.Index;

<b>import</b> org.neo4j.graphdb.traversal.Evaluation;

<b>import</b> org.neo4j.graphdb.traversal.Evaluator;

<b>import</b> org.neo4j.graphdb.traversal.Evaluators;

<b>import</b> org.neo4j.graphdb.traversal.Traverser;

<b>import</b> org.neo4j.kernel.EmbeddedReadOnlyGraphDatabase;

<b>import</b> org.neo4j.kernel.Traversal;

<b>import</b> org.neo4j.kernel.Uniqueness;

<b>import</b> org.neo4j.tooling.GlobalGraphOperations;

<b>import</b> com.alibaba.fastjson.JSON;

<b>public</b> <b>class</b> Neo4jTest00

{

GraphDatabaseService gds;

Node fromNode;

Node toNode;

Node companyNode;

Relationship relationship;

Relationship belongRelationship;

<b>private</b> <b>static</b> enum UserRelationship <b>implements</b> RelationshipType

{

FELLOW, BELONG

}

<b>public</b> <b>void</b> createDb()

{

String DB_PATH = "target/neo4j-test00.db";

GraphDatabaseFactory factory = <b>new</b> GraphDatabaseFactory();

gds = factory.newEmbeddedDatabase(DB_PATH);

GlobalGraphOperations ggo = GlobalGraphOperations.at(gds);

<b>try</b>(Transaction tx = gds.beginTx() )

{

fromNode = gds.createNode();

fromNode.setProperty("prop_key_table", "prop_value_table_person");

fromNode.setProperty("prop_key_name", "prop_value_name_mayu");

toNode = gds.createNode();

toNode.setProperty("prop_key_table", "prop_value_table_person");

toNode.setProperty("prop_key_name", "prop_value_name_liyanhong");

relationship = fromNode.createRelationshipTo(toNode,UserRelationship.FELLOW);

List<String> eventList = <b>new</b> ArrayList<String>();

//eventList.add("2013福布斯中国富豪榜:李彦宏第三、马化腾第五、马云第八 ");

//eventList.add("李彦宏推轻应用马云入股浏览器 移动入口争夺暗战升级 ");

eventList.add("2013fubushi zhongguo fuhaobang:liyanhong no.3 mahuateng no.5 mayu no.8 ");

eventList.add("liyanhong tui qinyingyong,mayu rugu liulanqi; yidong rukou zhengduo anzhan shengji");

relationship.setProperty("prop_key_event", JSON.toJSONString(eventList));

companyNode = gds.createNode();

companyNode.setProperty("prop_key_table", "company");

companyNode.setProperty("prop_key_name", "alibaba corp");

belongRelationship = fromNode.createRelationshipTo(companyNode,UserRelationship.BELONG);

belongRelationship.setProperty("event", "mayu ruhe zhuangkong alibaba? ");

tx.success();

Iterator<Node> iterator = ggo.getAllNodes().iterator();

<b>while</b> (iterator.hasNext())

{

Node node = iterator.next();

Iterator<String> keysIterator = node.getPropertyKeys().iterator();

System.out.println("nodeId=" + node.getId());

<b>while</b> (keysIterator.hasNext())

{

String key = keysIterator.next();

System.out.println("node property : " + key + "->" + node.getProperty(key));

}

Iterator<Relationship> relationshipsIterator = node.getRelationships().iterator();

<b>while</b> (relationshipsIterator.hasNext())

{

Relationship relationships = relationshipsIterator.next();

System.out.println("关系:" + relationships.getType());

Iterator<String> keysIterator2 = relationships.getPropertyKeys().iterator();

<b>while</b> (keysIterator2.hasNext())

{

String key = keysIterator2.next();

System.out.println("relationship property : "+ key + "->"

+ relationships.getProperty(key));

}

}

}

}

}

<b>public</b> <b>void</b> removeData()

{

<b>try</b> ( Transaction tx = gds.beginTx() )

{

belongRelationship.delete();

companyNode.delete();

tx.success();

}

}

<b>public</b> <b>void</b> stopDb()

{

gds.shutdown();

}

<b>public</b> <b>static</b> <b>void</b> main(String[] args)

{

Neo4jTest00 test00=<b>new</b> Neo4jTest00();

test00.createDb();

test00.removeData();

test00.stopDb();

}

}

上述程序执行后,会在target/neo4j-test00.db 下生成 neo4j 的 db 存储文件,

下面我们看几个主要的存储文件,来帮助我们对 neo4j 的存储格式有个直观的认识。

为了看文件的内容,笔者用二进制方式打开neo4j_exam的db存储文件,并用虚拟打印机输出到pdf 文件,并根据每个文件的格式,进行了着色。

3.8.2    neostore.nodestore.db.id 的内容

打开neo4j_exam的neostore.nodestore.db.id文件看到如下内容:

neostore.nodestore.db.id

id 文件的header 部分: sticky 值是0, nextFreeId是3,目前已回收可复用的 ID 是 02。

3.8.3    neostore.nodestore.db 的内容

neostore.nodestore.db

从neo4j_exam的neostore.nodestore.db文件内容可以看到,文件中保存了有 3 条node record 几率的数组和一个字符串“NodeStore v0.A.2”(文件类型描述TYPE_DESCRIPTOR和 neo4j 的 ALL_STORES_VERSION构成)。

其中3 条 node record 的内容如下:

a)        node_id=0 (即数组下标为0) 的node record 是在使用的, nextRelId=0, nextPropId=1, labels=0, extra=0

b)        node_id=1 (即数组下标为0) 的node record 是在使用的, nextRelId=0, nextPropId=3, labels=0, extra=0

c)        node_id=2 (即数组下标为0) 的node record 是已经释放了, nextRelId=1, nextPropId=4, labels=0, extra=0

结合 2.6.1 的源代码,可以的看到,fromNode 的 node_id=0, toNode的node_id=1, companyNode 的 node_id=2.

3.8.4    neostore.relationshipstore.db 的内容

neostore.relationshipstore.db

从neo4j_exam的neostore.relationshipstore.db文件内容可以看到,文件中保存了有 2 条 relationship record记录的数组和一个字符串“RelationshipStore v0.A.2”(文件类型描述TYPE_DESCRIPTOR和 neo4j 的 ALL_STORES_VERSION构成)。

其中2 个 relationship record 的内容如下:

字段 第1条记录 第2条记录
in_use 1 0
first_node 0 0
second_node 1 2
rel_type 0 1
first_prev_rel_id 1 2
first_next_rel_id -1 0
second_prev_rel_id 1 1
second_next_rel_id -1 -1
next_prop_id 5 6
first-in-chain-markers 3 3

3.8.5   neostore.relationshiptypestore.db的内容

neostore.relationshiptypestore.db

  • record[0].name_id=0×01
  • record[1].name_id=0×02

3.8.6   neostore.relationshiptypestore.db.names 的内容

neostore.relationshiptypestore.db.names

  • record[1]=”FELLOW”
  • record[2]=”BELONG”

3.8.7   neostore.propertystore.db的内容

neostore.propertystore.db

type=0xB 表示 SHORT_STRING, type=0×9 表示 STRING.

因为 companyNode 节点和 belongRelationship 关系已经删除,所以其属性property[4], property[5] , property[7] 的 block_header (key,type,value)部分填充为0。

3.8.8   neostore.propertystore.db.strings的内容

neostore.propertystore.db.strings

打开neo4j_exam的neostore.nodestore.db.id文件看到如上内容:

  •  第0个block 的前4个Bytes 保存 block_size=0×80, 即 block_header_size=8 和 string_block_size=120
  • 第1个block 的保存例子中关系relationship的属性值一部分: < ["2013fubushi zhongguo fuhaobang:liyanhong no.3 mahuateng no.5 mayu no.8 ","liyanhong tui qinyingyong,mayu rugu liulanq >, 其中 block_header的值如下:link_block=0, in_use=1, nr_of_bytes=0x78 , next_block=2
  • 第2个block 的保存例子中关系relationship的属性值一部分: < i; yidong rukou zhengduo anzhan shengji"] >, 其中 block_header的值如下:link_block=1, in_use=1, nr_of_bytes=0×28 , next_block=0xFFFFFFFF(即NULL)

3.8.9   neostore.propertystore.db.index的内容

neostore.propertystore.db.index

  • record[0].name_id=01
  • record[1].name_id=02
  • record[2].name_id=03
  • record[3].name_id=04

3.8.10 neostore.propertystore.db.index.keys的内容

neostore.propertystore.db.index.keys

  •  block[1]=”prop_key_table”
  • block[2]=”prop_key_name”
  • block[3]=”prop_key_event”
  • block[4]=”event”

4       参考

  1. <graph databases>
  2. http://blog.csdn.net/huaishu/article/details/11748927
  3. http://www.neo4j.org.cn/old-docs/

发表回复