我需要一些帮助来决定我的Neo4j数据库的正确索引策略。在数据库中,我有用户拥有项目,每个用户和项目都有一个修改的epoch整数值和一个UUID值(修剪后的Base64字符串)。我正在使用2.0-M6进行开发,因此我可以很好地使用基于schema的新索引来查询标签USER的“uuid”字段中的用户。
但索引用户的项目更复杂。我想做两个类型为“userUUID = X AND modified> Y”的查询,它应该返回所有具有比数字Y更大(更新)的修改整数的项目。但我也想做一个简单的搜索“userUUID = X,itemUUID = Z”,它应该返回一个节点。
在我目前对Lucene的非常有限的理解中,最好的解决方案可能是一个带有三个键“userUUID,itemUUID,modified”的索引,这样我就可以用compound query查询它。但是我究竟会如何创建这样一个索引,并且随着用户群的增长它会保持快速?索引应该主要在userUUID属性上进行优化,该属性在每个查询中,并且仅在itemUUID和修改后的整数之后。这可能吗?
另一个选项是为每个用户为修改后的值构建一个索引,然后使用一个联接键“userUUID + itemUUID”为直接项目访问构建一个索引。这比选项1更容易实现,因为Neo4j非常支持和记录单个键索引。但是,如果我说一百万用户,索引“modified-items-for-X”的索引仍然会很快,并且所有这些索引会占用我所有的内存吗?
This问题是相关的,但Lucene的数量要小得多。
EDIT。正如Stefan所猜测的那样,用户和项目与OWNS关系链接,UUID对于数据库中的每个节点都是唯一的。
为了进一步澄清,我正在寻找用于查询项目的最高性能解决方案:单个用户预计会有数千个项目,并且每个用户都会发出“userUUID = X AND modified> Y”查询以稳定的速度(甚至每分钟一次),“userUUID = X和itemUUID = Y”查询。所以每毫秒都算在这里。
答案 0 :(得分:1)
在Neo4j 2.0模式中,索引仅限于单个属性,但您可以为每个标签创建多个索引。我假设您使用的是标签User
和Item
,并且您的用户与其商品之间存在OWNS
关系。进一步的假设是uuids确实是唯一的并且不被多个节点共享。在这种情况下,我不会索引modified
属性。 uuids上只有一个索引:
CREATE INDEX ON :User(userUuid)
CREATE INDEX ON :Item(itemUuid)
请记住:应该使用索引来查找遍历的起点。
使用modfied > y
查找用户X的所有项目:
MATCH (user:User)-[:OWNS]->(item:Item)
WHERE user.userUuid={X} and item.modified > {Y]
RETURN item
要查找特定项目,只需:
MATCH (item:Item)
WHERE item.itemUuid={uuid}
RETURN item
如果你真的需要复合索引,你可以使用legacy indexing - 但架构索引更舒适。
另请注意,在撰写本文时,2.0是一个里程碑式的构建,这意味着它不是生产就绪的。
答案 1 :(得分:0)
为了将来参考,我最终选择了选项1,并为项目创建了一个三键索引(在Scala中):
val itemsIndex = neo4j.gds.index().forNodes("items")
itemsIndex.add(itemNode, "user", userUUID)
itemsIndex.add(itemNode, "item", itemNode.getProperty("uuid"))
itemsIndex.add(itemNode, "modified", new ValueContext(getProperty("modified").asInstanceOf[Long] ).indexNumeric())
然后用:
查询它itemsIndex.query( "user:\"" + userUUID) + "\" AND item:\"" + itemUUID)+ "\"")