我觉得我在这里要做很多额外的工作,因为有一些我不知道的事情会使其变得更容易!
因此,基本上,我试图吸引用户的访问者以及访问他们的人。
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)所以这是我不知道该怎么做的地方!我想要获取
created_at
,youVisited
项目的visitedYou
,但是我不知道如何在查询过程中将它们合并,因此最终使我一团糟: 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)中做了一些事情,这可能会变得更加容易,在此步骤中,将两个相互关联的独立数组(而不是RETURN)而不是RETURN
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 map projection功能,该功能可以更轻松地包括节点的某些或所有属性以及要在返回的结构中包含的其他属性。
使用查询段的示例:
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