Neo4j - 单个Lucene索引还是每个用户一个?

时间:2013-10-26 11:05:41

标签: lucene neo4j

我需要一些帮助来决定我的Neo4j数据库的正确索引策略。在数据库中,我有用户拥有项目,每个用户和项目都有一个修改的epoch整数值和一个UUID值(修剪后的Base64字符串)。我正在使用2.0-M6进行开发,因此我可以很好地使用基于schema的新索引来查询标签USER的“uuid”字段中的用户。

但索引用户的项目更复杂。我想做两个类型为“userUUID = X AND modified> Y”的查询,它应该返回所有具有比数字Y更大(更新)的修改整数的项目。但我也想做一个简单的搜索“userUUID = X,itemUUID = Z”,它应该返回一个节点。

  1. 在我目前对Lucene的非常有限的理解中,最好的解决方案可能是一个带有三个键“userUUID,itemUUID,modified”的索引,这样我就可以用compound query查询它。但是我究竟会如何创建这样一个索引,并且随着用户群的增长它会保持快速?索引应该主要在userUUID属性上进行优化,该属性在每个查询中,并且仅在itemUUID和修改后的整数之后。这可能吗?

  2. 另一个选项是为每个用户为修改后的值构建一个索引,然后使用一个联接键“userUUID + itemUUID”为直接项目访问构建一个索引。这比选项1更容易实现,因为Neo4j非常支持和记录单个键索引。但是,如果我说一百万用户,索引“modified-items-for-X”的索引仍然会很快,并且所有这些索引会占用我所有的内存吗?

  3. This问题是相关的,但Lucene的数量要小得多。

    EDIT。正如Stefan所猜测的那样,用户和项目与OWNS关系链接,UUID对于数据库中的每个节点都是唯一的。

    为了进一步澄清,我正在寻找用于查询项目的最高性能解决方案:单个用户预计会有数千个项目,并且每个用户都会发出“userUUID = X AND modified> Y”查询以稳定的速度(甚至每分钟一次),“userUUID = X和itemUUID = Y”查询。所以每毫秒都算在这里。

2 个答案:

答案 0 :(得分:1)

在Neo4j 2.0模式中,索引仅限于单个属性,但您可以为每个标签创建多个索引。我假设您使用的是标签UserItem,并且您的用户与其商品之间存在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)+ "\"")