Neo4j-DB 中最常见的元组
Most common tuples in Neo4j-DB
我的数据库中的订单和产品节点通过包含关系连接:
(:order)-[:contains]->(:product)
我想知道是否有可能找到以相同顺序出现的最常见的 n 元组产品。
恐怕这是不可能的,因为我有超过 1500 种产品,即使对于小 n,这些产品之间可能的组合数量也非常多,例如1500^4 ≈ 5*10^12.
我为 n=3 编写了以下测试查询:
MATCH (o:order)-[r:contains]->(p:product)
WITH count(r) as NrProds, o
MATCH (o)-[r:contains]->(p:product)
WHERE NrProds > 3
WITH o
MATCH (o)-[r1:contains]->(p1:product),(o)-[r2:contains]->(p2:product),(o)-[r3:contains]->(p3:product)
WITH o,p1,p2,p3,count(r1) as r1,count(r2) as r2,count(r3) as r3
WITH o,p1,p2,p3,
CASE WHEN r1<r2 AND r1<r3 THEN r1
WHEN r2<r1 AND r2<r3 THEN r2
WHEN r3<r1 AND r3<r2 THEN r3
END as result
WITH result,o,p1,p2,p3
RETURN count(result) as NrPurchs, o.Id,p1.name,p2.name,p3.name ORDER BY NrPurchs DESC
首先,我确保不考虑任何产品数量少于 3 的订单,因为这些订单占所有订单的很大一部分,然后我匹配这些订单中的包含关系。
我的计算机没有完成查询,考虑到正在创建的大型连接,这并不奇怪。
有没有一种不用查询那么多可能性就能找到元组的方法,这样我的电脑就可以完成计算了?
正如您所指出的,产品的组合数量太多,因此最好从订单端开始生成元组,以仅生成现有的元组。
您的过滤器之前有一个不必要的 MATCH
,以下应该足以过滤掉带有 :
的订单
MATCH (o:order)-[r:contains]->(p:product)
WITH count(r) as NrProds, o
WHERE NrProds >= 3 // note >= sign for orders with 3 and more
WITH o
...
或者如果您的 order
仅针对产品使用 contains
关系:
MATCH (o:order)
WITH o,size((o)-[:contains]->()) as NrProds
WHERE NrProds >= 3
WITH o
...
为了避免重复,通过按 ID、名称等对相同产品进行排序来过滤掉相同产品的排列。(此 where 子句仅适用于唯一 names/ids。如果您有重复项,则需要 <= )
...
MATCH (o)-[r1:contains]->(p1:product),(o)-[r2:contains]->(p2:product),(o)-[r3:contains]->(p3:product)
WHERE p1.name < p2.name AND p2.name < p3.name
...
然后 return 每个元组的订单数:
RETURN p1,p2,p3,COUNT(o) as c
(如果您在单个订单和产品之间有多个 contains
关系,您应该使用 COUNT(DISTINCT o)
)
最后return只有N个元组:
ORDER BY c DESC LIMIT {n}
整个查询:
MATCH (o:order)
WITH o,size((o)-[:contains]->()) as NrProds
WHERE NrProds >= 3
WITH o
MATCH
(o)-[r1:contains]->(p1:product),
(o)-[r2:contains]->(p2:product),
(o)-[r3:contains]->(p3:product)
WHERE p1.name < p2.name AND p2.name < p3.name
RETURN p1,p2,p3,COUNT(o) as c
ORDER BY c DESC LIMIT {n}
我的数据库中的订单和产品节点通过包含关系连接:
(:order)-[:contains]->(:product)
我想知道是否有可能找到以相同顺序出现的最常见的 n 元组产品。
恐怕这是不可能的,因为我有超过 1500 种产品,即使对于小 n,这些产品之间可能的组合数量也非常多,例如1500^4 ≈ 5*10^12.
我为 n=3 编写了以下测试查询:
MATCH (o:order)-[r:contains]->(p:product)
WITH count(r) as NrProds, o
MATCH (o)-[r:contains]->(p:product)
WHERE NrProds > 3
WITH o
MATCH (o)-[r1:contains]->(p1:product),(o)-[r2:contains]->(p2:product),(o)-[r3:contains]->(p3:product)
WITH o,p1,p2,p3,count(r1) as r1,count(r2) as r2,count(r3) as r3
WITH o,p1,p2,p3,
CASE WHEN r1<r2 AND r1<r3 THEN r1
WHEN r2<r1 AND r2<r3 THEN r2
WHEN r3<r1 AND r3<r2 THEN r3
END as result
WITH result,o,p1,p2,p3
RETURN count(result) as NrPurchs, o.Id,p1.name,p2.name,p3.name ORDER BY NrPurchs DESC
首先,我确保不考虑任何产品数量少于 3 的订单,因为这些订单占所有订单的很大一部分,然后我匹配这些订单中的包含关系。 我的计算机没有完成查询,考虑到正在创建的大型连接,这并不奇怪。
有没有一种不用查询那么多可能性就能找到元组的方法,这样我的电脑就可以完成计算了?
正如您所指出的,产品的组合数量太多,因此最好从订单端开始生成元组,以仅生成现有的元组。
您的过滤器之前有一个不必要的 MATCH
,以下应该足以过滤掉带有 :
MATCH (o:order)-[r:contains]->(p:product)
WITH count(r) as NrProds, o
WHERE NrProds >= 3 // note >= sign for orders with 3 and more
WITH o
...
或者如果您的 order
仅针对产品使用 contains
关系:
MATCH (o:order)
WITH o,size((o)-[:contains]->()) as NrProds
WHERE NrProds >= 3
WITH o
...
为了避免重复,通过按 ID、名称等对相同产品进行排序来过滤掉相同产品的排列。(此 where 子句仅适用于唯一 names/ids。如果您有重复项,则需要 <= )
...
MATCH (o)-[r1:contains]->(p1:product),(o)-[r2:contains]->(p2:product),(o)-[r3:contains]->(p3:product)
WHERE p1.name < p2.name AND p2.name < p3.name
...
然后 return 每个元组的订单数:
RETURN p1,p2,p3,COUNT(o) as c
(如果您在单个订单和产品之间有多个 contains
关系,您应该使用 COUNT(DISTINCT o)
)
最后return只有N个元组:
ORDER BY c DESC LIMIT {n}
整个查询:
MATCH (o:order)
WITH o,size((o)-[:contains]->()) as NrProds
WHERE NrProds >= 3
WITH o
MATCH
(o)-[r1:contains]->(p1:product),
(o)-[r2:contains]->(p2:product),
(o)-[r3:contains]->(p3:product)
WHERE p1.name < p2.name AND p2.name < p3.name
RETURN p1,p2,p3,COUNT(o) as c
ORDER BY c DESC LIMIT {n}