3.8 示例1:neo4j_exam
下面看一个简单的例子,然后看一下几个主要的存储文件,有助于理解<3–neo4j存储结构>描述的neo4j 的存储格式。
3.8.1 neo4j_exm 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
|
< 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文件看到如下内容:
id 文件的header 部分: sticky 值是0, nextFreeId是3,目前已回收可复用的 ID 是 02。
3.8.3 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 的内容
从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的内容
- record[0].name_id=0×01
- record[1].name_id=0×02
3.8.6 neostore.relationshiptypestore.db.names 的内容
- record[1]=”FELLOW”
- record[2]=”BELONG”
3.8.7 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的内容
打开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的内容
- 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的内容
- block[1]=”prop_key_table”
- block[2]=”prop_key_name”
- block[3]=”prop_key_event”
- block[4]=”event”