[英]Neo4j - I have 2 collects where the data is related. How do I merge them together?
我覺得我在這里做了很多額外的工作,因為有一些我不知道的事情會讓它變得更容易!
所以基本上,我試圖獲得用戶的訪問者,以及誰訪問了他們。
1)這是我正在使用的當前查詢:
MATCH (you:User {user_id: { id }})
WITH you
OPTIONAL MATCH(you)-[yvr:VISIT]->(youVisited:User)
WITH you, collect(youVisited) as youVisited, collect(yvr) as yvr
OPTIONAL MATCH (visitedYou:User)-[vyr:VISIT]->(you)
WITH youVisited, collect(visitedYou) as visitedYou, collect(vyr) as vyr, yvr
RETURN
youVisited,
visitedYou,
yvr,
vyr,
length(filter(m in vyr where m.seen = false)) as unseenCount
(底部被切斷,但
youVisited
是yvr
, visitedYou
就是vyr
,右被切斷但unseenCount
是有)
╒══════════════════════════════╤══════════════════════════════╤══════════════════════════════╤══════════════════════════════╤═════════════╕
│"youVisited" │"visitedYou" │"yvr" │"vyr" │"unseenCount"│
╞══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪═════════════╡
│[{"user_id":"auth0|58784f52734│[{"user_id":"auth0|5865bfa8087│[{"created_at":1484294208011,"│[{"created_at":1484317325539,"│2 │
│b0307b61ea401"},{"user_id":"au│52725eaaae8f9"},{"user_id":"au│seen":false},{"created_at":148│seen":false},{"created_at":148│ │
│th0|587805cb995ac47e7dbe42ae"}│th0|587805cb995ac47e7dbe42ae"}│4294735987,"seen":false},{"cre│4321428350,"seen":false}] │ │
│,{"user_id":"auth0|5865bfa8087│] │ated_at":1484293423029,"seen":│ │ │
│52725eaaae8f9"},{"user_id":"au│ │false},{"created_at":148429420│ │ │
│th0|58669ac4d4aed25972f7c33e"}│ │1140,"seen":false},{"created_a│ │ │
│,{"user_id":"auth0|586a0337b94│ │t":1484294214268,"seen":false}│ │ │
│a4d77c1f77cb3"}] │ │] │ │ │
└──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴─────────────┘
2) 所以這就是我不知道該怎么做的地方! 我想要獲取youVisited
、 visitedYou
項目的created_at
,但我不知道如何在查詢期間合並它們,所以我最終弄得一團糟:
const nodes = {
youVisited: row.get('youVisited').map((yv, index) => Object.assign(
yv.properties,
{ created_at: row.get('yvr')[index].properties.created_at },
)),
visitedYou: row.get('visitedYou').map((vy, index) => Object.assign(
vy.properties,
{ created_at: row.get('vyr')[index].properties.created_at },
)),
unseenCount: row.get('unseenCount'),
};
3)然后我必須獲取其他數據並再次找到映射...
const youVisitedPromises = nodes.youVisited.map(yv => usersIndex.getObject(yv.user_id));
const visitedYouPromises = nodes.visitedYou.map(vy => usersIndex.getObject(vy.user_id));
let [youVisited, visitedYou] = await Promise.all([
youVisitedPromises, visitedYouPromises,
].map(Promise.all, Promise));
youVisited = youVisited.map(yv => Object.assign(
yv,
{ visited_at: _.get(_.find(nodes.youVisited, { user_id: yv.objectID }), 'created_at') },
));
visitedYou = visitedYou.map(vy => Object.assign(
vy,
{ visited_at: _.get(_.find(nodes.visitedYou, { user_id: vy.objectID }), 'created_at') },
));
result = {
youVisited,
visitedYou,
unseenCount: nodes.unseenCount,
};
我認為這可能是容易得多,如果我沒有在步驟1中的東西),其中,代替回報之間的相互關系如兩個獨立的陣列youVisited
到yvr
,我只是有一個數組包含所有數據對象youVisited: [{ user_id, created_at, seen }, ...]
。 我如何用 Neo4j 做到這一點?
我最終需要的預期最終result
如下所示:
result = {
youVisited: [{ user_id: 'a', nickname: 'foo', visited_at: 12931093 }, ...],
visitedYou: [{ user_id: 'b', nickname: 'bar', visited_at: 12931099 }, ...],
unseenCount: 1,
};
完整代碼,如果還有其他任何幫助:
const cypherGetVisitors = `
MATCH (you:User {user_id: { id }})
WITH you
OPTIONAL MATCH(you)-[yvr:VISIT]->(youVisited:User)
WITH you, collect(youVisited) as youVisited, collect(yvr) as yvr
OPTIONAL MATCH (visitedYou:User)-[vyr:VISIT]->(you)
WITH youVisited, collect(visitedYou) as visitedYou, collect(vyr) as vyr, yvr
RETURN
youVisited,
visitedYou,
yvr,
vyr,
length(filter(m in vyr where m.seen = false)) as unseenCount
`;
const queryResult = await retry(this.connector._bolt._pool._maxIdle + 1, async () => {
const session = this.connector.session();
try {
const res = await session.run(cypherGetVisitors, { id });
session.close();
return res;
} catch (neo4jError) {
throw new Error(neo4jError);
}
});
const row = queryResult.records[0];
const nodes = {
youVisited: row.get('youVisited').map((yv, index) => Object.assign(
yv.properties,
{ created_at: row.get('yvr')[index].properties.created_at },
)),
visitedYou: row.get('visitedYou').map((vy, index) => Object.assign(
vy.properties,
{ created_at: row.get('vyr')[index].properties.created_at },
)),
unseenCount: row.get('unseenCount'),
};
const youVisitedPromises = nodes.youVisited.map(yv => usersIndex.getObject(yv.user_id));
const visitedYouPromises = nodes.visitedYou.map(vy => usersIndex.getObject(vy.user_id));
let [youVisited, visitedYou] = await Promise.all([
youVisitedPromises, visitedYouPromises,
].map(Promise.all, Promise));
youVisited = youVisited.map(yv => Object.assign(
yv,
{ visited_at: _.get(_.find(nodes.youVisited, { user_id: yv.objectID }), 'created_at') },
));
visitedYou = visitedYou.map(vy => Object.assign(
vy,
{ visited_at: _.get(_.find(nodes.visitedYou, { user_id: vy.objectID }), 'created_at') },
));
result = {
youVisited,
visitedYou,
unseenCount: nodes.unseenCount,
};
看起來您已經有了一個有效的解決方案(使用 COLLECT() 以及您想要的值的新映射)。
如果您碰巧需要所有值+更多值,您可以使用 3.1 地圖投影功能,它可以更輕松地包含節點的部分或全部屬性以及您希望在返回結構中出現的其他屬性。
使用查詢段的示例:
OPTIONAL MATCH(you)-[yvr:VISIT]->(youVisited:User)
WITH you, collect(youVisited {.*, created_at: yvr.created_at}) as youVisted
在這種情況下,.* 表示包含節點 (youVisited) 的所有屬性,但如果您只需要某些屬性,則可以僅包含相關鍵,並且鍵/值對將包含在返回的映射中。 因此,如果您只需要 user_id 和 created_at,這將起作用:
OPTIONAL MATCH(you)-[yvr:VISIT]->(youVisited:User)
WITH you, collect(youVisited {.user_id, created_at: yvr.created_at}) as youVisted
所以我發現我可以在收集期間構建一個對象。 這有什么問題,或者有更好的方法嗎?
MATCH (you:User {user_id: { id }})
WITH you
OPTIONAL MATCH(you)-[yvr:VISIT]->(youVisited:User)
WITH you, collect({user_id: youVisited.user_id, created_at: yvr.created_at}) as youVisited
OPTIONAL MATCH (visitedYou:User)-[vyr:VISIT]->(you)
WITH youVisited, collect({user_id: visitedYou.user_id, created_at: vyr.created_at}) as visitedYou, collect(vyr) as vyr
RETURN
youVisited,
visitedYou,
length(filter(m in vyr where m.seen = false)) as unseenCount
從其他來源獲取其余數據后,我仍然需要做所有其他地圖工作,但這與 Neo4j 無關。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.