Tài liệu truy vấn Firestore với mảng tương tự (Node.js / Admin SDK)

Aug 16 2020

Hãy tưởng tượng bạn có mảng này

[10.3, 14, 12.4, 3.5]

và trong DB của bạn, bạn cũng có hai tài liệu với các mảng đó:

First document -> [10, 13.1, 0, -10]
Second document -> [0, 0, 0, 0]

Bây giờ hãy tưởng tượng rằng bạn có +1000000 tài liệu với hai mảng giống nhau (xen kẽ giữa mỗi mảng) ... Có cách nào để lấy tất cả các tài liệu có giá trị tương tự như mảng hiện tại của bạn không?

Ý tôi là, một cái gì đó như thế này:

   ...
   .where("array", "isSimilar", yourArray)
   .get()

Vì vậy, tôi nhận được tất cả các tài liệu có mảng:

[10, 13.1, 0, -10]

Hay cách duy nhất là tải xuống từng tài liệu đơn lẻ, thứ gì đó có thể thực sự chậm, sau đó lặp lại và tìm kiếm tài liệu tương tự nhất? Tôi nghĩ điều này có thể thực sự thú vị khi nói về "vị trí điểm tương tự", "tuần mà người dùng đã giảm cân tương tự", ...

Cảm ơn.

Trả lời

3 JayCodist Aug 16 2020 at 09:20

Hiện tại, firestore không hỗ trợ loại truy vấn đó. Vì vậy, tôi khuyên bạn nên cập nhật cấu trúc của mình để bao gồm trường Chuỗi để so sánh mảng. Vì vậy, mỗi tài liệu sẽ giống như sau:

{
   array: [12, 11, 8, 9],
   arrayStr: "12,11,8,9",
   ...
}

Bạn có thể đạt được cấu trúc này đơn giản bằng cách gọi doc.array.join(",")tất cả các tài liệu hiện có và lưu giá trị vào tài liệu.

Sau đó, có thể thực hiện so sánh với truy vấn firestore, như sau:

const arrToCompare = [12, 11, 8, 9];
const snapshot = await firestore().collection(collection).where("arrayStr", "==", arrToCompare.join(",")).get();
...

CẬP NHẬT: Để so sánh theo độ tương tự thay vì bình đẳng, một cách tiếp cận khả thi là áp dụng logic "độ tương tự" của bạn cho arrayStrtrường trong quá trình tạo. Ví dụ: nếu bạn muốn dung sai sự khác biệt nhỏ hơn 0,5, bạn có thể sử dụng Math.round()trên các phần tử mảng trước khi lưu dưới dạng chuỗi. Như vậy:

const array = [12.2, 10.7, 8.111, 9.0];
const arrayStr = array.map(num => Math.round(num)).join(","); //"12,11,8,9"

Sau đó, bạn sẽ truy vấn như sau:

const arrToCompare = [12, 11, 8, 9];
const snapshot = await firestore().collection(collection).where("arrayStr", "==", arrToCompare.map(num => Math.round(num)).join(",")).get();
// Results would include arrays like [12.2, 10.7, 8.111, 9.0]
...

Tất nhiên, bạn có thể thay đổi đối số được chuyển sang Math.round()để tăng hoặc giảm mức độ dung sai cho các so sánh