|
239 | 239 | LOCAL_COMMUNITY_TOP_OUTSIDE_RELS = 10
|
240 | 240 |
|
241 | 241 | LOCAL_COMMUNITY_SEARCH_QUERY = """
|
242 |
| -WITH collect(node) as nodes, avg(score) as score, collect({{id: elementId(node), score:score}}) as metadata |
243 |
| -WITH score, nodes,metadata, |
244 |
| -collect {{ |
245 |
| - UNWIND nodes as n |
246 |
| - MATCH (n)<-[:HAS_ENTITY]->(c:Chunk) |
247 |
| - WITH c, count(distinct n) as freq |
248 |
| - RETURN c |
249 |
| - ORDER BY freq DESC |
250 |
| - LIMIT {topChunks} |
251 |
| -}} AS chunks, |
252 |
| -collect {{ |
253 |
| - UNWIND nodes as n |
254 |
| - MATCH (n)-[:IN_COMMUNITY]->(c:__Community__) |
255 |
| - WITH c, c.community_rank as rank, c.weight AS weight |
256 |
| - RETURN c |
257 |
| - ORDER BY rank, weight DESC |
258 |
| - LIMIT {topCommunities} |
259 |
| -}} AS communities, |
260 |
| -collect {{ |
261 |
| - unwind nodes as n |
262 |
| - unwind nodes as m |
263 |
| - match (n)-[r]->(m) |
264 |
| - RETURN distinct r |
265 |
| - // todo should we have a limit here? |
266 |
| -}} as rels, |
267 |
| -collect {{ |
268 |
| - unwind nodes as n |
269 |
| - match path = (n)-[r]-(m:__Entity__) |
270 |
| - where not m in nodes |
271 |
| - with m, collect(distinct r) as rels, count(*) as freq |
272 |
| - ORDER BY freq DESC LIMIT {topOutsideRels} |
273 |
| - WITH collect(m) as outsideNodes, apoc.coll.flatten(collect(rels)) as rels |
274 |
| - RETURN {{ nodes: outsideNodes, rels: rels }} |
275 |
| -}} as outside |
| 242 | +WITH collect(node) AS nodes, |
| 243 | + avg(score) AS score, |
| 244 | + collect({{id: elementId(node), score: score}}) AS metadata |
| 245 | + |
| 246 | +WITH score, nodes, metadata, |
| 247 | + |
| 248 | + collect {{ |
| 249 | + UNWIND nodes AS n |
| 250 | + MATCH (n)<-[:HAS_ENTITY]->(c:Chunk) |
| 251 | + WITH c, count(distinct n) AS freq |
| 252 | + RETURN c |
| 253 | + ORDER BY freq DESC |
| 254 | + LIMIT {topChunks} |
| 255 | + }} AS chunks, |
| 256 | + |
| 257 | + collect {{ |
| 258 | + UNWIND nodes AS n |
| 259 | + MATCH (n)-[:IN_COMMUNITY]->(c:__Community__) |
| 260 | + WITH c, c.community_rank AS rank, c.weight AS weight |
| 261 | + RETURN c |
| 262 | + ORDER BY rank, weight DESC |
| 263 | + LIMIT {topCommunities} |
| 264 | + }} AS communities, |
| 265 | + |
| 266 | + collect {{ |
| 267 | + UNWIND nodes AS n |
| 268 | + UNWIND nodes AS m |
| 269 | + MATCH (n)-[r]->(m) |
| 270 | + RETURN DISTINCT r |
| 271 | + // TODO: need to add limit |
| 272 | + }} AS rels, |
| 273 | + |
| 274 | + collect {{ |
| 275 | + UNWIND nodes AS n |
| 276 | + MATCH path = (n)-[r]-(m:__Entity__) |
| 277 | + WHERE NOT m IN nodes |
| 278 | + WITH m, collect(distinct r) AS rels, count(*) AS freq |
| 279 | + ORDER BY freq DESC |
| 280 | + LIMIT {topOutsideRels} |
| 281 | + WITH collect(m) AS outsideNodes, apoc.coll.flatten(collect(rels)) AS rels |
| 282 | + RETURN {{ nodes: outsideNodes, rels: rels }} |
| 283 | + }} AS outside |
276 | 284 | """
|
277 | 285 |
|
278 | 286 | LOCAL_COMMUNITY_SEARCH_QUERY_SUFFIX = """
|
279 |
| -RETURN {chunks: [c in chunks | c.text], |
280 |
| - communities: [c in communities | c.summary], |
281 |
| - entities: [n in nodes | apoc.coll.removeAll(labels(n),["__Entity__"])[0] + ":"+ n.id + " " + coalesce(n.description, "")], |
282 |
| - relationships: [r in rels | startNode(r).id+" "+type(r)+" "+endNode(r).id], |
283 |
| - outside: { |
284 |
| - nodes: [n in outside[0].nodes | apoc.coll.removeAll(labels(n),["__Entity__"])[0] + ":"+n.id + " " + coalesce(n.description, "")], |
285 |
| - relationships: [r in outside[0].rels | apoc.coll.removeAll(labels(startNode(r)),["__Entity__"])[0] + ":"+startNode(r).id+" "+type(r)+" "+apoc.coll.removeAll(labels(startNode(r)),["__Entity__"])[0] + ":"+endNode(r).id]} |
286 |
| - } AS text, score, {entities:metadata} as metadata |
| 287 | +RETURN { |
| 288 | + chunks: [c IN chunks | c.text], |
| 289 | + communities: [c IN communities | c.summary], |
| 290 | + entities: [ |
| 291 | + n IN nodes | |
| 292 | + CASE |
| 293 | + WHEN size(labels(n)) > 1 THEN |
| 294 | + apoc.coll.removeAll(labels(n), ["__Entity__"])[0] + ":" + n.id + " " + coalesce(n.description, "") |
| 295 | + ELSE |
| 296 | + n.id + " " + coalesce(n.description, "") |
| 297 | + END |
| 298 | + ], |
| 299 | + relationships: [ |
| 300 | + r IN rels | |
| 301 | + startNode(r).id + " " + type(r) + " " + endNode(r).id |
| 302 | + ], |
| 303 | + outside: { |
| 304 | + nodes: [ |
| 305 | + n IN outside[0].nodes | |
| 306 | + CASE |
| 307 | + WHEN size(labels(n)) > 1 THEN |
| 308 | + apoc.coll.removeAll(labels(n), ["__Entity__"])[0] + ":" + n.id + " " + coalesce(n.description, "") |
| 309 | + ELSE |
| 310 | + n.id + " " + coalesce(n.description, "") |
| 311 | + END |
| 312 | + ], |
| 313 | + relationships: [ |
| 314 | + r IN outside[0].rels | |
| 315 | + CASE |
| 316 | + WHEN size(labels(startNode(r))) > 1 THEN |
| 317 | + apoc.coll.removeAll(labels(startNode(r)), ["__Entity__"])[0] + ":" + startNode(r).id + " " |
| 318 | + ELSE |
| 319 | + startNode(r).id + " " |
| 320 | + END + |
| 321 | + type(r) + " " + |
| 322 | + CASE |
| 323 | + WHEN size(labels(endNode(r))) > 1 THEN |
| 324 | + apoc.coll.removeAll(labels(endNode(r)), ["__Entity__"])[0] + ":" + endNode(r).id |
| 325 | + ELSE |
| 326 | + endNode(r).id |
| 327 | + END |
| 328 | + ] |
| 329 | + } |
| 330 | +} AS text, |
| 331 | +score, |
| 332 | +{entities: metadata} AS metadata |
287 | 333 | """
|
288 | 334 |
|
289 | 335 | LOCAL_COMMUNITY_DETAILS_QUERY_PREFIX = """
|
|
293 | 339 | """
|
294 | 340 | LOCAL_COMMUNITY_DETAILS_QUERY_SUFFIX = """
|
295 | 341 | WITH *
|
296 |
| -UNWIND chunks as c |
| 342 | +UNWIND chunks AS c |
297 | 343 | MATCH (c)-[:PART_OF]->(d:Document)
|
298 |
| -RETURN [c {.*, embedding:null, fileName:d.fileName, fileSource:d.fileSource}] as chunks, |
299 |
| -[community in communities | community {.*, embedding:null}] as communities, |
300 |
| -[node in nodes+outside[0].nodes | {element_id:elementId(node), labels:labels(node), properties:{id:node.id,description:node.description}}] as nodes, |
301 |
| -[r in rels+outside[0].rels | {startNode:{element_id:elementId(startNode(r)), labels:labels(startNode(r)), properties:{id:startNode(r).id,description:startNode(r).description}}, |
302 |
| - endNode:{element_id:elementId(endNode(r)), labels:labels(endNode(r)), properties:{id:endNode(r).id,description:endNode(r).description}}, |
303 |
| - relationship: {type:type(r), element_id:elementId(r)}}] as entities |
| 344 | +RETURN |
| 345 | + [ |
| 346 | + c { |
| 347 | + .*, |
| 348 | + embedding: null, |
| 349 | + fileName: d.fileName, |
| 350 | + fileSource: d.fileSource |
| 351 | + } |
| 352 | + ] AS chunks, |
| 353 | + [ |
| 354 | + community IN communities | |
| 355 | + community { |
| 356 | + .*, |
| 357 | + embedding: null |
| 358 | + } |
| 359 | + ] AS communities, |
| 360 | + [ |
| 361 | + node IN nodes + outside[0].nodes | |
| 362 | + { |
| 363 | + element_id: elementId(node), |
| 364 | + labels: labels(node), |
| 365 | + properties: { |
| 366 | + id: node.id, |
| 367 | + description: node.description |
| 368 | + } |
| 369 | + } |
| 370 | + ] AS nodes, |
| 371 | + [ |
| 372 | + r IN rels + outside[0].rels | |
| 373 | + { |
| 374 | + startNode: { |
| 375 | + element_id: elementId(startNode(r)), |
| 376 | + labels: labels(startNode(r)), |
| 377 | + properties: { |
| 378 | + id: startNode(r).id, |
| 379 | + description: startNode(r).description |
| 380 | + } |
| 381 | + }, |
| 382 | + endNode: { |
| 383 | + element_id: elementId(endNode(r)), |
| 384 | + labels: labels(endNode(r)), |
| 385 | + properties: { |
| 386 | + id: endNode(r).id, |
| 387 | + description: endNode(r).description |
| 388 | + } |
| 389 | + }, |
| 390 | + relationship: { |
| 391 | + type: type(r), |
| 392 | + element_id: elementId(r) |
| 393 | + } |
| 394 | + } |
| 395 | + ] AS entities |
304 | 396 | """
|
305 | 397 |
|
306 | 398 | CHAT_MODE_CONFIG_MAP= {
|
|
0 commit comments