เอกสารแบบสอบถาม Firestore พร้อมอาร์เรย์ที่คล้ายกัน (Node.js / Admin SDK)

Aug 16 2020

ลองนึกภาพคุณมีอาร์เรย์นี้

[10.3, 14, 12.4, 3.5]

และในฐานข้อมูลของคุณคุณยังมีเอกสารสองชุดที่มีอาร์เรย์เหล่านี้:

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

ทีนี้ลองนึกดูว่าคุณมีเอกสารมากกว่า 1000000 รายการที่มีอาร์เรย์สองอาร์เรย์เหมือนกัน (สลับกันระหว่างแต่ละอัน) ... มีวิธีใดบ้างที่จะรับเอกสารทั้งหมดที่มีค่าใกล้เคียงกับอาร์เรย์ปัจจุบันของคุณ?

ฉันหมายถึงสิ่งนี้:

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

เพื่อให้ฉันได้รับเอกสารทั้งหมดที่มีอาร์เรย์:

[10, 13.1, 0, -10]

หรือวิธีเดียวคือดาวน์โหลดเอกสารทุกฉบับสิ่งที่อาจช้ามากจากนั้นทำซ้ำและค้นหาสิ่งที่คล้ายกันมากที่สุด? ฉันคิดว่าสิ่งนี้น่าสนใจมากเมื่อพูดถึง "ตำแหน่งคะแนนที่คล้ายกัน", "สัปดาห์ที่ผู้ใช้ลดน้ำหนักได้ใกล้เคียงกัน", ...

ขอบคุณ.

คำตอบ

3 JayCodist Aug 16 2020 at 09:20

ในขณะนี้ firestore ไม่รองรับข้อความค้นหาประเภทนั้น ดังนั้นฉันขอแนะนำให้คุณอัปเดตโครงสร้างของคุณเพื่อรวมฟิลด์สตริงสำหรับการเปรียบเทียบอาร์เรย์ ดังนั้นแต่ละเอกสารจะมีลักษณะดังนี้:

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

คุณสามารถบรรลุโครงสร้างนี้ได้ง่ายๆโดยเรียกdoc.array.join(",")เอกสารที่มีอยู่ทั้งหมดและบันทึกค่าลงในเอกสาร

จากนั้นจะสามารถทำการเปรียบเทียบกับแบบสอบถาม firestore ได้ดังนี้:

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

อัปเดต: หากต้องการเปรียบเทียบตามความเหมือนแทนที่จะเป็นความเท่าเทียมแนวทางที่เป็นไปได้คือการใช้ตรรกะ "ความเหมือน" ของคุณกับarrayStrฟิลด์ระหว่างการสร้าง ตัวอย่างเช่นหากคุณต้องการให้ความแตกต่างน้อยกว่า 0.5 สามารถยอมรับได้คุณสามารถใช้Math.round()กับองค์ประกอบอาร์เรย์ก่อนที่จะบันทึกเป็นสตริง ชอบมาก:

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

จากนั้นคุณจะสอบถามดังนี้:

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

แน่นอนคุณสามารถเปลี่ยนอาร์กิวเมนต์ที่ส่งผ่านไปMath.round()เพื่อเพิ่มหรือลดระดับความอดทนต่อการเปรียบเทียบได้