2014-09-20 123 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堆大小。

相關問題