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”