permintaan untuk membandingkan dua daftar di CQL (Cypher)

Saya memiliki data mengenai produk tertentu dan tanggal pembeliannya dalam database grafik di neo4j

Produk 1. A, B, C, D, E, F, G Tanggal pembelian 6 hingga 8 Juli

Pola pembeliannya adalah sebagai berikut

6 Juli - A,B,C,D 7 Juli - A,B,C,D,E 8 Juli - A,B,D,E,F,G

Tanggal pembelian disimpan sebagai atribut di node Pesanan. (yaitu o.tanggal_pembelian)

Saya menulis kueri Cypher untuk menghitung jumlah pembelian per hari

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

Saya ingin mengubah ini menjadi kueri untuk memberi tahu saya jumlah total produk baru yang dibeli setiap hari, dibandingkan dengan hari sebelumnya. yaitu 7 Juli 1 8 Juli 2

Ada saran?


person MohanVS    schedule 08.07.2016    source sumber
comment
Tampaknya mengembalikan ini dalam kueri bisa jadi cukup sulit. Mungkin lebih mudah untuk membuat dan menyimpan informasi ini di db itu sendiri, tetapi hanya jika Anda hanya memerlukannya untuk pesanan dengan tanggal pembelian berturut-turut, dan tanpa pemfilteran atau kriteria tambahan apa pun. Apakah itu akan berhasil untuk Anda, atau apakah itu perlu diselesaikan sepenuhnya dalam kueri?   -  person InverseFalcon    schedule 10.07.2016
comment
Cara pertanyaan ini diutarakan membuat saya bertanya-tanya apakah ini adalah pekerjaan rumah atau soal ujian, bukan contoh kecil dari sistem yang perlu Anda terapkan. Apa pun kasusnya, saya akan menggunakan rangkaian produk yang lebih bervariasi untuk kasus pengujian Anda. Dengan data Anda saat ini hanya ada 1 atau 2 produk baru, dan Anda tidak pernah menghapus produk, tampaknya rentan terhadap kesalahan positif saat menguji solusi. Coba beberapa kombinasi lainnya, seperti tanggal 6 - A, B (2 baru) 7 - B, C, D (2 baru) 8 - A, B, C, D, E, F, G (4 baru) 9 - A, Z (1 baru)   -  person InverseFalcon    schedule 11.07.2016


Jawaban (2)


Gunakan fungsi filter untuk membandingkan daftar:

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

atau pemahaman daftar

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

Saya pikir Anda ingin melakukan pendekatan ini secara berbeda. Kueri yang operasinya harus menggunakan data dari baris sebelumnya sangat sulit untuk disatukan. Sulit untuk mencapai titik di mana Anda dapat mereferensikan data dari dua baris berbeda secara bersamaan, dan mampu melakukan operasi yang sama di antara setiap rangkaian dua baris adalah masalah sulit lainnya.

Jika Anda memiliki hubungan antara pesanan Anda, seperti [:Next] antara masing-masing pesanan dalam urutan menaik, maka masalah yang memusingkan ini menjadi sepele.

Kueri berikut tidak memiliki pemesanan, saya serahkan kepada Anda, karena contoh Anda menyarankan tanggal pembelian mungkin dalam format string, yang tidak akan dipesan dengan benar sebagaimana adanya.

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

Ini akan mengembalikan baris dengan pasangan pesanan, menampilkan produk baru dan jumlah produk baru di antara setiap pesanan. Anda dapat dengan mudah menghapus o1 dan/atau NewProds dari pengembalian Anda jika Anda tidak membutuhkannya, yang hanya akan memberi Anda pesanan dan jumlah produk baru dalam pesanan tersebut.

Kekurangan yang jelas di sini adalah rantai pesanan pertama (yang tidak ada pesanan sebelumnya) hilang.

Modifikasi berikut akan memperbaikinya, jika Anda memerlukannya:

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

Hubungan :Next antara o1 dan o2 sekarang bersifat opsional, sehingga memungkinkan untuk mencocokkan pesanan yang tidak memiliki pesanan sebelumnya, namun kita hanya perlu menghitungnya HANYA ketika tidak ada pesanan sebelumnya (karena jika tidak, setiap pesanan dapat cocok dengan dirinya sendiri sebagai o1 dan o2 o2, bukan hanya pesanan di awal rantai), dan akan membantu jika menambahkan satu syarat tambahan bahwa pesanan harus memiliki pesanan berikutnya. Ini berarti kami tidak akan mendapatkan kembali apa pun untuk pesanan tunggal, yang mungkin diinginkan jika hubungan :Next hanya bersifat sementara, atau dibuat dengan cepat (untuk dihapus setelah selesai) di antara pesanan tertentu untuk menjalankan kueri semacam ini; Anda tidak ingin mengambil pesanan lain yang tidak Anda minati.

Terakhir, ada kekacauan dalam menciptakan hubungan :Next. Artikel ini berisi beberapa hal yang sangat menarik tentang bekerja dengan daftar tertaut di neo4j, tetapi bagiannya yang relevan bagi kami saat ini terlihat seperti ini (salin dan tempel dari artikel):

...
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)))

Anda harus mengganti bagian awal dan klausa WITH pertama dengan pencocokan dan pengurutan pesanan yang Anda minati. Anda akan mengumpulkannya dan mengulangi daftar itu untuk menciptakan hubungan :Next di antara mereka. Anda tentu saja dapat menggunakan label yang berbeda, terutama jika Anda sudah memiliki atau berencana menggunakan :Hubungan berikutnya antara pesanan untuk kasus penggunaan lainnya (karena hal itu akan mengacaukan kueri Anda, dan penghapusan hubungan tersebut setelah Anda selesai mungkin akan terhapus secara tidak sengaja. hubungan yang tidak berhubungan dengan label yang sama).

Ketika saya menyiapkan hubungan berikutnya, saya mengalami hal yang aneh di mana :Hubungan selanjutnya dibuat menunjuk dari dan ke simpul yang sama. Jika hal itu terjadi pada Anda, Anda sebaiknya membersihkannya setelah :Pembuatan hubungan berikutnya dengan:

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

Dan nanti, jika label :Next Anda bersifat sementara dan Anda perlu membersihkannya setelah mendapatkan data yang Anda perlukan, cukup hapus semua hubungan :Next antara node pesanan:

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