簡體   English   中英

Neo4j Cypher查詢基於特征增量查找節點

[英]Neo4j Cypher query for finding nodes based on characteristics deltas

在我的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查詢參數)相互區分。

例如,我需要從價格= 50和價格delta = 150開始在Neo4j數據庫中找到所有產品。作為輸出,我希望得到以下產品:

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

計算看起來像:

起點價格= 50,因此第一個產品的價格應不低於50且不高於200(50 + 150)。 所以基於此,我們從我們的目錄中找到了一個價格= 100的產品。第二個產品的價格不應低於100且不超過250(100 + 150)..這個產品的價格= 220 ..第三個價格不低於220而不是370.這是一個價格= 305的產品

能否請您展示一個可以找到這類產品的Cypher查詢。

這在Cypher中執行起來相當復雜。 我遇到的唯一方法是使用REDUCE()函數和CASE語句,有條件地將產品添加到列表末尾,如果它在列表中最后一個產品的價格差值內。

請記住,使用這種方法無法使產品的處理短路。 如果總產品有100萬,並且我們在有序的產品列表中發現只有前兩種產品屬於該增量模式,則此查詢將繼續檢查這些百萬種產品中的每一種產品,盡管它們都不會是添加到我們的列表中。

此查詢應該適合您。

WITH {startPrice:50, delta:150} as params
MATCH (p:Product)
WHERE p.price >= params.startPrice
WITH params, p
ORDER BY p.price asc
WITH params, COLLECT(p) as products
WITH params, TAIL(products) as products, HEAD(products) as first
WHERE first.price <= params.startPrice + params.delta
WITH REDUCE(prods = [first], prod in products | 
  CASE WHEN prod.price <= LAST(prods).price + params.delta 
       THEN prods + prod 
       ELSE prods END) as products
RETURN products

該解決方案需要在迭代期間傳輸中間結果。 一個有趣的問題,因為今天cypher沒有直接提供這種可能性。 作為練習(草圖)使用APOC -library中的apoc.periodic.commit程序:

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

作為一種替代解決方案,查詢速度應該快得多,但需要更多維護和保養以保持正常工作(特別是在快速變化的產品價格數據時),您可以按升序價格順序在產品節點之間創建關系,並將增量保持為關系屬性。

以下是使用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()謂詞應該在達到超過所需delta的關系時切斷變量匹配。

當然,缺點是您需要確保每個影響此鏈表結構的操作(添加或刪除產品和更改產品價格)都能正確調整結構,您可能需要考慮鎖定方法以確保線程安全因此,如果產品和/或價格同時更新,則不會破壞鏈表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM