แบบสอบถามเพื่อเปรียบเทียบสองรายการใน CQL (Cypher)

ฉันมีข้อมูลเกี่ยวกับผลิตภัณฑ์บางอย่างและวันที่ซื้อในฐานข้อมูลกราฟใน neo4j

สินค้า 1. A, B, C, D, E, F, G วันที่ซื้อ 6 ถึง 8 กรกฎาคม

รูปแบบการซื้อมีดังนี้

6 กรกฎาคม - A,B,C,D 7 กรกฎาคม - A,B,C,D,E 8 กรกฎาคม - A,B,D,E,F,G

วันที่ซื้อจะถูกจัดเก็บเป็นแอตทริบิวต์ในโหนดคำสั่งซื้อ (เช่น o.purchase_date)

ฉันเขียนแบบสอบถาม Cypher เพื่อนับจำนวนการซื้อต่อวัน

Match (o :Order)-[:Contains]->(p :Product) 
return o.purchase_date, count(p)

Output:
o.purchase_date       count(p)
6th July                   4
7th July                   5
8th July                   6

ฉันต้องการแก้ไขสิ่งนี้เพื่อสอบถามเพื่อบอกจำนวนผลิตภัณฑ์ใหม่ที่ซื้อในแต่ละวันเทียบกับวันก่อนหน้า เช่น 7 กรกฎาคม 1 8 กรกฎาคม 2

มีข้อเสนอแนะอะไรบ้าง?


person MohanVS    schedule 08.07.2016    source แหล่งที่มา
comment
ดูเหมือนว่าการส่งคืนสิ่งนี้ในแบบสอบถามอาจค่อนข้างยาก การสร้างและจัดเก็บข้อมูลนี้ในฐานข้อมูลอาจง่ายกว่า แต่เฉพาะในกรณีที่คุณต้องการเฉพาะสำหรับคำสั่งซื้อที่มีวันที่ซื้อติดต่อกัน และไม่มีการกรองหรือเกณฑ์เพิ่มเติม มันจะได้ผลสำหรับคุณหรือจำเป็นต้องแก้ไขบางอย่างภายในแบบสอบถามหรือไม่?   -  person InverseFalcon    schedule 10.07.2016
comment
วิธีเรียบเรียงคำถามนี้ทำให้ฉันสงสัยว่านี่เป็นการบ้านหรือปัญหาการทดสอบ แทนที่จะเป็นตัวอย่างเล็กๆ น้อยๆ ของระบบที่คุณต้องนำไปใช้ ไม่ว่าในกรณีใด ฉันจะทำงานกับชุดผลิตภัณฑ์ที่หลากหลายมากขึ้นสำหรับกรณีทดสอบของคุณ ด้วยข้อมูลปัจจุบันของคุณ มีผลิตภัณฑ์ใหม่เพียง 1 หรือ 2 รายการ และคุณไม่เคยลบผลิตภัณฑ์ออก ดูเหมือนว่าจะมีแนวโน้มที่จะเกิดผลบวกลวงเมื่อทำการทดสอบโซลูชัน ลองชุดค่าผสมอื่นๆ เช่น อันดับ 6 - A, B (2 ใหม่) 7 - B, C, D (2 ใหม่) 8 - A, B, C, D, E, F, G (4 ใหม่) 9 - A, Z (1 ใหม่)   -  person InverseFalcon    schedule 11.07.2016


คำตอบ (2)


ใช้ฟังก์ชันตัวกรองเพื่อเปรียบเทียบรายการ:

WITH [ 'A', 'B', 'C', 'D']      as List1, 
     [ 'A', 'B', 'C', 'D', 'E'] as List2
RETURN FILTER ( product in List2 WHERE NOT product in List1 ) as newProduct

หรือรายการความเข้าใจ

WITH [ 'A', 'B', 'C', 'D']      as List1, 
     [ 'A', 'B', 'C', 'D', 'E'] as List2
RETURN [product in List2 WHERE NOT product in List1] as newProduct
person stdob--    schedule 10.07.2016

ฉันคิดว่าคุณจะต้องการใช้แนวทางนี้แตกต่างออกไป การสืบค้นที่การดำเนินการต้องใช้ข้อมูลจากแถวก่อนหน้านั้นยากต่อการรวบรวม การไปถึงจุดที่คุณสามารถอ้างอิงข้อมูลจากสองแถวที่แตกต่างกันในเวลาเดียวกันนั้นเป็นเรื่องยาก และความสามารถในการดำเนินการแบบเดียวกันระหว่างแต่ละชุดของสองแถวก็เป็นอีกหนึ่งปัญหาที่ยาก

หากคุณมีความสัมพันธ์ระหว่างคำสั่งซื้อของคุณแทน เช่น [:ถัดไป] ระหว่างแต่ละคำสั่งซื้อจากน้อยไปหามาก อาการปวดหัวของปัญหาจะกลายเป็นเรื่องเล็กน้อย

แบบสอบถามต่อไปนี้ไม่มีการเรียงลำดับ ฉันจะปล่อยให้คุณเป็นเช่นนั้น เนื่องจากตัวอย่างของคุณแนะนำว่าวันที่ซื้ออาจอยู่ในรูปแบบสตริง ซึ่งจะเรียงลำดับไม่ถูกต้องตามที่เป็นอยู่

MATCH (o1:Order)-[:Next]->(o2:Order)-[:Contains]->(p2:Product)
WHERE NOT (o1)-[:Contains]->(p2)
WITH o1, o2, COLLECT(p2) AS NewProds
RETURN o1, o2, NewProds, SIZE(NewProds) AS NewProdCnt

ซึ่งจะส่งคืนแถวที่มีคู่คำสั่งซื้อ โดยแสดงทั้งผลิตภัณฑ์ใหม่และจำนวนผลิตภัณฑ์ใหม่ระหว่างคำสั่งซื้อแต่ละรายการ คุณสามารถลบ o1 และ/หรือ NewProds ออกจากการคืนสินค้าได้อย่างง่ายดายหากคุณไม่ต้องการ ซึ่งจะแจ้งเฉพาะคำสั่งซื้อและจำนวนผลิตภัณฑ์ใหม่ในคำสั่งซื้อนั้นเท่านั้น

ข้อบกพร่องที่ชัดเจนที่นี่คือห่วงโซ่คำสั่งซื้อแรกสุด (ซึ่งไม่มีคำสั่งซื้อก่อนหน้า) หายไป

การปรับเปลี่ยนต่อไปนี้ควรแก้ไขปัญหาดังกล่าว หากคุณต้องการ:

MATCH (o1:Order)-[:Next*0..1]->(o2:Order)-[:Contains]->(p2:Product)
WHERE (o1 = o2 AND NOT (:Order)-[:Next]->(o2) AND (o2)-[:Next]->(:Order)) 
OR NOT (o1)-[:Contains]->(p2)
WITH o1, o2, COLLECT(p2) AS NewProds
RETURN o1, o2, NewProds, SIZE(NewProds) AS NewProdCnt

:ความสัมพันธ์ถัดไประหว่าง o1 และ o2 เป็นทางเลือก ทำให้สามารถจับคู่กับคำสั่งซื้อที่ไม่มีลำดับก่อนหน้า แต่เราต้องนับเฉพาะเมื่อไม่มีลำดับก่อนหน้าเท่านั้น (มิฉะนั้น ทุกคำสั่งซื้อสามารถจับคู่กับตัวมันเองเป็นทั้ง o1 และ o2 แทนที่จะเป็นเพียงคำสั่งซื้อที่จุดเริ่มต้นของห่วงโซ่) และช่วยเพิ่มเงื่อนไขเพิ่มเติมหนึ่งข้อที่คำสั่งซื้อต้องมีคำสั่งซื้อถัดไป ซึ่งหมายความว่าเราจะไม่คืนสิ่งใดๆ สำหรับคำสั่งซื้อเดี่ยวๆ ซึ่งอาจต้องการได้หากความสัมพันธ์ :Next เกิดขึ้นชั่วคราวเท่านั้น หรือสร้างขึ้นอย่างรวดเร็ว (จะถูกลบออกเมื่อเสร็จสิ้น) ระหว่างคำสั่งซื้อบางคำสั่งซื้อสำหรับการเรียกใช้แบบสอบถามประเภทนี้ คุณคงไม่อยากรับคำสั่งซื้ออื่นใดที่คุณไม่สนใจ

สุดท้ายนี้ การสร้างความสัมพันธ์ :Next มีความยุ่งเหยิงไปหมดตั้งแต่เริ่มต้น บทความนี้ มีเนื้อหาที่น่าสนใจมากเกี่ยวกับการทำงานกับ Linked Lists ใน neo4j แต่ส่วนหนึ่ง ที่เกี่ยวข้องกับเราตอนนี้มีลักษณะดังนี้ (คัดลอกและวางจากบทความ):

...
WITH elem ORDER BY elem.name ASC
WITH COLLECT(elem) AS elems
FOREACH (n IN RANGE(0, LENGTH(elems)-2) |
  FOREACH (prec IN [elems[n]] |
    FOREACH (next IN [elems[n+1]] |
      MERGE prec-[:Next]->next)))

คุณควรแทนที่ส่วนเริ่มต้นและส่วนแรกด้วยคำสั่งที่สนใจด้วยการจับคู่และการเรียงลำดับคำสั่งซื้อที่คุณสนใจ คุณจะรวบรวมและวนซ้ำรายการนั้นเพื่อสร้างความสัมพันธ์ :ถัดไป ระหว่างพวกเขา แน่นอน คุณสามารถใช้ป้ายกำกับอื่นได้ โดยเฉพาะอย่างยิ่งหากคุณมีหรือวางแผนที่จะใช้ :Next ความสัมพันธ์ระหว่างคำสั่งซื้อสำหรับกรณีการใช้งานอื่น ๆ (ซึ่งอาจทำให้ข้อความค้นหาของคุณยุ่งเหยิง และการลบความสัมพันธ์เหล่านั้นเมื่อคุณทำเสร็จแล้วอาจกำจัดออกไปโดยไม่ตั้งใจ ของความสัมพันธ์ที่ไม่เกี่ยวข้องกับป้ายกำกับเดียวกัน)

เมื่อฉันตั้งค่าความสัมพันธ์ครั้งถัดไป ฉันพบสิ่งที่น่าสงสัยโดยที่ :ความสัมพันธ์ถัดไปถูกสร้างขึ้นโดยชี้จากและไปยังโหนดเดียวกัน หากสิ่งนั้นเกิดขึ้นกับคุณ คุณจะต้องล้างมันหลังจาก :Next การสร้างความสัมพันธ์ด้วย:

MATCH (a:Order)-[r:Next]->(a)
DELETE r

และในภายหลัง หากป้ายกำกับ :Next ของคุณเป็นแบบชั่วคราว และคุณจำเป็นต้องล้างข้อมูลหลังจากที่คุณได้รับข้อมูลที่ต้องการแล้ว ให้ลบความสัมพันธ์ :Next ทั้งหมดระหว่างโหนดคำสั่งซื้อ:

MATCH (:Order)-[r:Next]-(:Order)
DELETE r
person InverseFalcon    schedule 10.07.2016