2014-09-20 109 views
1

我想在我的数据库中的所有节点上实现唯一的ID属性,但需要将其应用于现有数据。我使用Ruby来执行生成IDS,然后从那里运行Cypher查询。我想避免一个查询找到缺少该属性的节点,另一个要单独设置每个节点上的属性,因为这需要total_nodes + 1查询。Neo4j:为所有匹配查询的节点分配唯一值

最初,我想我可以做这样的事情:

MATCH (n:`#{label}`) WHERE NOT HAS(n.my_id) SET n.my_id = '#{gen_method}' RETURN DISTINCT(true) 

。当然,这是行不通的,因为它会在Ruby中调用gen_method一次,然后将Neo4j的尝试设置的所有节点ID,以那一个价值。

我现在在想,最好先在Ruby中生成大量的ID,然后将其包含在Cypher查询中。我想循环遍历匹配的节点,并将缺失的属性设置为等于数组中相应的索引。逻辑应该是这样的

MATCH NODES WHERE GIVEN PROPERTY IS NULL, LIMIT TO 10,000 
CREATE A COLLECTION OF THOSE NODES 
SET NEW UUIDS ARRAY (provided by Ruby) AS "IDS_ARRAY" 
FOR EACH NODE IN COLLECTION 
    SET GIVEN PROPERTY VALUE = CORRESPONDING INDEX POSITION IN "IDS_ARRAY" 
RETURN COUNT OF NODES WHERE GIVEN PROPERTY IS NULL 

基于返回值,它会知道多少次这样做。 Cypher有一个foreach循环,但我如何做到这一点,特别是如果我的unique_ids阵列从Cypher查询中的字符串开始?

unique_ids = ['first', 'second', 'third', 'etc'] 
i = 0 
for node in matched_nodes 
    node.my_id_property = unique_ids[i] 
    i += 1 
end 

这有可能吗?有没有不同的方式来处理这将工作?

回答

1

Got it!发现http://java.dzone.com/articles/neo4j-cypher-creating,它提供了一个这样做的方法,并且http://jexp.de/blog/2014/03/quickly-create-a-100k-neo4j-graph-data-model-with-cypher-only/指出了range函数。我的Ruby代码的初稿如下所示:

def add_ids_to(model) 
    label = model.mapped_label_name 
    property = model.primary_key 
    total = 1 

    until total == 0 
    total = Neo4j::Session.query("MATCH (n:`#{label}`) WHERE NOT has(n.#{property}) RETURN COUNT(n) as ids").first.ids 
    return if total == 0 
    to_set = total > 900 ? 900 : total 
    new_ids = [].tap do |ids_array| 
       to_set.times { ids_array.push "'#{new_id_for(model)}'" } 
       end 
    Neo4j::Session.query("MATCH (n:`#{label}`) WHERE NOT has(n.#{property}) 
     with COLLECT(n) as nodes, [#{new_ids.join(',')}] as ids 
     FOREACH(i in range(0,#{to_set - 1})| 
     FOREACH(node in [nodes[i]]| 
      SET node.#{property} = ids[i])) 
     RETURN distinct(true) 
     limit #{to_set}") 
    end 
end 

我认为这些都很可读。关于查询本身,我使用的是Neo4j.rb和neo4j-core,但是我在这种情况下跳过了Cypher DSL。我将每个查询限制为最多900个节点,因为这是我能够可靠地运行而不会耗尽内存的最高值。调整您的JVM堆大小。

相关问题