Neo4j Cypher查询基于特征增量查找节点

时间:2017-02-01 11:12:50

标签: neo4j cypher

在我的Neo4j / Spring Data Neo4j 4项目中,我有一个实体:Product

每个Product都有一个Integer属性 - price

例如,我有以下产品的价格:

Product1.price = 100
Product2.price = 305
Product3.price = 10000
Product4.price = 1000
Product5.price = 220

产品之间没有关联关系。

我需要根据初始价格值(Cypher查询参数)查找通过最大价格增量(Cypher查询参数)彼此不同的产品集(路径)。

例如,我需要找到Neo4j数据库中的所有产品,从price = 50开始,价格delta = 150.作为输出,我希望得到以下产品:

Product1.price = 100
Product5.price = 220
Product2.price = 305

计算如下:

起点价格= 50因此第一个产品的价格应不低于50且不高于200(50 + 150)。所以基于此,我们从我们的目录中找到了一个价格= 100的产品。第二个产品的价格不应低于100且不超过250(100 + 150)..这个产品的价格= 220 ..第三个价格不低于220而不是370.这是一个价格= 305

的产品

请您展示一个Cypher查询,它会找到这类产品。

3 个答案:

答案 0 :(得分:1)

这在Cypher中执行相当复杂。我遇到的唯一方法是使用REDUCE()函数和CASE语句,有条件地将产品添加到列表末尾,如果它在列表中最后一个产品的价格差值内。

请记住,使用这种方法无法使产品处理短路。如果总产品有100万,并且我们在有序的产品列表中发现只有前两种产品属于该增量模式,则此查询将继续检查这些百万种产品中的每一种产品,尽管它们都不会是添加到我们的列表中。

此查询应该适合您。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);     
    setContentView(R.layout.my_activity);

    CustomView customView = (CustomView) findViewById(R.id.custom_view);
    customView.setImage(R.drawable.some_icon);
    customView.setText("Hello world");
}

答案 1 :(得分:1)

解决方案需要在迭代期间传输中间结果。一个有趣的问题,因为今天cypher没有直接提供这种可能性。作为练习(草图),使用modifier中的apoc.periodic.commit过程 - library:

CALL apoc.create.uuid() YIELD uuid
CALL apoc.periodic.commit("
  MERGE (H:tmpVars {id: {tmpId}})
  ON CREATE SET H.prices = [],
                H.lastPrice = {lastPrice}, 
                H.delta = {delta} 
  WITH H
  MATCH (P:Product) WHERE P.price > H.lastPrice AND 
                          P.price < H.lastPrice + H.delta
  WITH H, max(P.price) as lastPrice
  SET H.lastPrice = lastPrice, 
      H.prices = H.prices + lastPrice
  RETURN 1
  ", {tmpId: uuid, delta: 150, lastPrice: 50}
) YIELD updates, executions, runtime
MATCH (T:tmpVars {id: uuid}) 
WITH T, T.prices as prices DETACH DELETE T
WITH prices 
UNWIND prices as price
MATCH (P:Product) WHERE P.price = price
RETURN P ORDER BY P.price ASC

答案 2 :(得分:1)

作为一种替代解决方案,其查询速度应该更快,但需要更多维护和保养以保持正常工作(特别是在快速变化的产品价格数据时),您可以按升序价格顺序在产品节点之间创建关系,并保持将三角洲作为关系属性。

以下是使用APOC程序创建此内容的方法:

MATCH (p:Product)
WITH p 
ORDER BY p.price ASC
WITH apoc.coll.pairsMin(COLLECT(p)) as products
UNWIND products as prodPairs
WITH prodPairs[0] as prod1, prodPairs[1] as prod2
CREATE (prod1)-[r:NextProd]->(prod2)
SET r.delta = prod2.price - prod1.price

以下是设置后的问题。

WITH {startPrice:50, delta:150} as params
WITH params, params.startPrice + params.delta as ceiling
MATCH (start:Product)
WHERE params.startPrice <= start.price <= ceiling
WITH start, params
ORDER BY start.price ASC
LIMIT 1
MATCH (start)-[r:NextProd*0..]->(product:Product)
WHERE ALL(rel in r WHERE rel.delta <= params.delta)
RETURN DISTINCT product

这应该是一个相当快的查询,因为当ALL()谓词达到超过所需增量的关系时,它应该切断变量匹配。

当然,缺点是您需要确保每个影响此链表结构的操作(添加或删除产品和更改产品价格)都能正确调整结构,您可能需要考虑锁定方法确保线程安全,以便在产品和/或价格同时更新时不会破坏链表。