2016-09-15 73 views
0

我創建人從JSON,在Neo4j中,類似這樣的東西(JSON是空白的,因爲隱私/太多數據)標記節點:爲Neo4j匹配塊,以防止「空屬性值」 - 錯誤

WITH [] AS contacts 
UNWIND contacts AS contact 

但有時人數據沒有一個名字和名字或姓氏, 所以查詢失敗:

MERGE(personBind:Person {first_name: contact.first_name, last_name: contact.last_name}) 

它給這個錯誤:

Cannot merge node using null property value 

是否有可能有一個MATCH,與它像這些塊:

NOT MATCH 
CANT CREATE (Don't do something with person, but make other stuff) 
CAN CREATE (Make person and relations to person, and make other stuff) 
ON MATCH (Make relations to person, and make other stuff) 

這是其他的代碼,我需要使用, 不過是「附加」到人(有時候會失敗):

FOREACH (addr IN contact.addrs | 
      MERGE addrPath=((zipBind:ZipCode {zipcode: addr.zipcode})-[nz:NUMBER_IN_ZIPCODE]->(houseBind:House {number: addr.housenumber})<-[ns:NUMBER_IN_STREET]-(streetBind:Street)) 

      MERGE(personBind)-[:WORKS_AT]->(houseBind) 
      ) 

     FOREACH(phoneValue IN contact.phone | MERGE(phoneBind:Phone {number: phoneValue.value}) MERGE(personBind)-[:REACHABLE_BY]->(phoneBind)) 
     FOREACH(emailValue IN contact.email | MERGE(emailBind:Email {email: emailValue.value}) MERGE(personBind)-[:REACHABLE_BY]->(emailBind)) 

回答

1

將您的查詢分爲兩部分:首先解決通用部分(聯繫人數據),然後爲具有名字和姓氏的人過濾查詢併合並其他部分。

UNWIND [] AS contact 
WITH contact 
UNWIND contact.addrs AS addr 
MERGE (zipBind:ZipCode {zipcode: addr.zipcode}) 
MERGE (streetBind:Street) # does this need properties, like a name? 
MERGE (streetBind) - [:NUMBER_IN_STREET] ->(houseBind:House {number: addr.housenumber}) 
MERGE (zipBind) -[:NUMBER_IN_ZIPCODE]-> (houseBind) 
WITH contact, COLLECT(houseBind) AS houseBinds 
UNWIND contact.phone AS phoneValue 
MERGE(phoneBind:Phone {number: phoneValue.value}) 
WITH contact, houseBinds, COLLECT(phoneBind) AS phoneBinds 
UNWIND contact.email AS emailValue 
    MERGE(emailBind:Email {email: emailValue.value}) 
WITH contact, houseBinds, phoneBinds, COLLECT(emailBind) AS emailBinds 

<NOW FILTER FOR CONTACTS WITH PERSON DATA> 

WHERE exists(contact.first_name) AND EXISTS(contact.last_name) 
MERGE(personBind:Person {first_name: contact.first_name, last_name: contact.last_name}) 

FOREACH(housebind IN housebinds|MERGE(personBind)-[:WORKS_AT]->(houseBind)) 

    FOREACH(phoneBind IN phoneBinds | MERGE(personBind)-[:REACHABLE_BY]->(phoneBind)) 

    FOREACH(emailBind IN emailBinds |) MERGE(personBind)-[:REACHABLE_BY]->(emailBind)) 

如果你需要的是沒有人的名字後來在查詢行,您可以更改過濾器的步驟創建兩個列表,一個有名字,一說沒有,但是這不是更復雜你的問題需要。

編輯:您的Street節點沒有屬性,所以此查詢將爲每行找到相同的街道。你想在那裏指定什麼嗎?

+0

上面的代碼給出了一個'houseBind'值缺失錯誤。你的編輯工作,我只需要修復語法的東西:在addrPath後面添加「)」,並刪除「|」在'UNWIND'之後。我現在明白,你可以用'WITH'來「收集」數據,並將它傳遞給下一個塊。第一次我看到'WITH'和'WHERE'的組合:) –

+0

嗯,我在圖中還看到'Street'的空白節點,可能是因爲'House.number'有時是新引入的。 –

+1

感謝您的錯字捕捉。我繼續爲你分解'addrPath'合併,解決你的街頭問題。每當你合併一個模式,你匹配_entire_模式,或者你創建_entire_模式,所以如果該addr模式的任何部分是新的(數字,郵編或街道),你會得到重複使它全部一次。嘗試併合並較小的模式並使用別名將它們綁定在一起。 –

0

使用的foreach和案例的結合:

UNWIND [ {lastName: 'Fam1', firstName: 'Nam1'}, {lastName: 'Fam2'} ] 
     as contact 
FOREACH(x in CASE WHEN (NOT contact.lastName is NULL AND 
          NOT contact.firstName is NULL 
      ) THEN [1] ELSE [] END | 
    MERGE (personBind:TMP:Person {first_name: contact.firstName, 
           last_name: contact.lastName} 
) 
) 

http://www.markhneedham.com/blog/2014/06/17/neo4j-load-csv-handling-conditionals/