2015-07-05 32 views
3

我正在研究一個小項目,並且我有一個約60k節點和這些節點之間500k關係的數據集。節點有兩種類型。第一類是配方,第二類是配料。食譜是由以下成分組成:遍歷所有節點並將每個節點與每個節點進行比較

(ingredient)-[:IS_PART_OF]->(recipe) 

我的目標是找到兩種食譜共享多少種常見食材。我已成功地獲得與下面的查詢比較一個配方所有其他人(第一個與所有其他人)這樣的信息:

MATCH (recipe:RECIPE{ ID: 1000000 }),(other) 
    WHERE (other.ID >= 1000001 AND other.ID <= 1057690) 
    OPTIONAL MATCH (recipe:RECIPE)<-[:IS_PART_OF]-(ingredient:INGREDIENT)-     [:IS_PART_OF]->(other) 
    WITH ingredient, other 
    RETURN other.ID, count(distinct ingredient.name) 
    ORDER BY other.ID DESC 

我的第一個問題:我怎樣才能獲得兩個配方中的所有成分的數量以相互只計算一次的方式(R1和R2的聯合 - > R1 U R2)

第二個問題:是否可以編寫一個循環來遍歷所有配方並檢查常見配料?目標是比較每個配方與所有其他。我認爲這應該返回(n-1)*(n/2)行。

我已經嘗試過上述問題。即使使用LIMITSKIP,我也無法在整個集合上運行代碼。我已經改變了我的查詢,以便它可以讓我我的分區設置相應:直到我得到我的手一個更好的機器,這將足以在

MATCH (recipe1)<-[:IS_PART_OF]-(ingredient:INGREDIENT)-[:IS_PART_OF]->(recipe2) 
WHERE (recipe2.ID >= 1000000 AND recipe2.ID <= 1000009) AND (recipe1.ID >= 1000000 AND recipe1.ID <= 1000009) AND (recipe1.ID < recipe2.ID) 
RETURN recipe1.ID, count(distinct ingredient.name) AS MutualIngredients, recipe2.ID 
ORDER BY recipe1.ID 

我還沒有解決我的第一個問題:我怎樣才能得到兩個食譜的所有成分的數量,以互相計算一次的方式(R1和R2的聯合 - > R1 U R2)

回答

2

你需要玩這個,但它的將是與此類似:

MATCH (recipe1:RECIPE)<-[:IS_PART_OF]-(ingred:INGREDIENT)-[:IS_PART_OF]->(recipe2:RECIPE) 
WHERE ID(recipe1) < ID(recipe2) 
RETURN recipe1, collect(ingred.name), recipe2 
ORDER BY recipe1.ID 

匹配模式可以讓你所有的常見成分的兩個配方之間。 WHERE條款確保您不會將自己的食譜與自己進行比較(因爲它會與自己共享所有成分)。 return語句只是給你兩個你正在比較的食譜,以及它們的共同之處。

雖然這將是O(n^2),並且將是很慢

UPDATE採取了妮可的建議,這是一個很好的建議。這應該保證每一對只被考慮一次。

+1

您應該添加'WHERE ID(RECIPE1)

+0

好主意;已更新 – FrobberOfBits

+0

感謝您的回答和建議。我試圖運行查詢並運行了一段時間,然後有時因Java堆錯誤,GC錯誤或數據庫斷開連接(我已檢查聯機,它也是一個GC錯誤)而終止。我認爲我的電腦操作太緊張了。我試圖增加堆空間和其他一些調整,但沒有成功。是否可以將操作分成幾個較小的操作而不改變數據本身並仍然獲得所需的結果? – user3745794

0

解決:只是爲了分享,如果別人需要它:

MATCH (recipe1)<-[:IS_PART_OF]-(ingredient:INGREDIENT)-[:IS_PART_OF]->(recipe2) 
    MATCH (recipe1)<-[:IS_PART_OF]-(ingredient1:INGREDIENT) 
    MATCH (recipe2)<-[:IS_PART_OF]-(ingredient2:INGREDIENT) 
    WHERE (recipe2.ID >= 1000000 AND recipe2.ID <= 1000009) AND (recipe1.ID >= 1000000 AND recipe1.ID <= 1000009) AND (recipe1.ID < recipe2.ID) 
    RETURN recipe1.ID, count(distinct ingredient1.name) + count(distinct ingredient2.name) - count(distinct ingredient.name) AS RecipesUnion, recipe2.ID 
    ORDER BY recipe1.ID