cari

Rumah  >  Soal Jawab  >  teks badan

Kaedah Firestore untuk mendapatkan dokumen rawak dalam koleksi

Adalah penting untuk apl saya dapat memilih berbilang dokumen secara rawak daripada koleksi dalam Firebase.

Memandangkan tiada fungsi asli terbina dalam dalam Firebase (setahu saya) untuk melaksanakan pertanyaan untuk melakukan ini, pemikiran pertama saya ialah menggunakan kursor pertanyaan untuk memilih indeks permulaan dan penamat rawak, dengan mengandaikan saya mempunyai koleksi of numbers Bilangan dokumen dalam .

Pendekatan ini berfungsi, tetapi hanya dengan cara yang terhad, kerana setiap dokumen akan disampaikan secara berurutan dengan jirannya setiap kali, walau bagaimanapun, saya boleh mencapai rawak jika saya dapat memilih dokumen mengikut indeksnya dalam pertanyaan Dokumentasi koleksi induknya, tetapi masalahnya ialah saya tidak dapat mencari sebarang dokumentasi yang menerangkan cara melakukan ini, atau walaupun mungkin untuk melakukan ini.

Ini yang saya nak buat, pertimbangkan seni bina firestore berikut:

root/
  posts/
     docA
     docB
     docC
     docD

Kemudian di pihak pelanggan saya (saya berada dalam persekitaran Swift) saya ingin menulis pertanyaan yang melakukan ini:

db.collection("posts")[0, 1, 3] // would return: docA, docB, docD

Bolehkah saya melakukan sesuatu yang serupa? Sebagai alternatif, adakah terdapat cara lain untuk memilih dokumen rawak dengan cara yang sama?

Tolong bantu.

P粉277305212P粉277305212403 hari yang lalu804

membalas semua(2)saya akan balas

  • P粉668113768
  • P粉985686557

    P粉9856865572023-10-20 09:50:51

    Menggunakan indeks yang dijana secara rawak dan pertanyaan mudah, anda boleh memilih dokumen secara rawak daripada kumpulan koleksi atau koleksi dalam Cloud Firestore.

    Jawapan ini terbahagi kepada 4 bahagian, setiap satu dengan pilihan yang berbeza:

    1. Bagaimana untuk menjana indeks rawak
    2. Bagaimana untuk menanyakan indeks rawak
    3. Pilih berbilang dokumen rawak
    4. Reseed untuk rawak yang konsisten

    Bagaimana untuk menjana indeks rawak

    Asas jawapan ini adalah untuk mencipta medan indeks yang, apabila diisih dalam susunan menaik atau menurun, akan menyebabkan semua dokumen diisih secara rawak. Terdapat beberapa cara yang berbeza untuk mencipta ini, jadi mari kita lihat 2, bermula dengan kaedah yang paling mudah diakses.

    Mengenal versi secara automatik

    Jika anda menggunakan ID automatik yang dijana secara rawak yang disediakan dalam pustaka pelanggan kami, anda boleh menggunakan sistem yang sama untuk memilih dokumen secara rawak. Dalam kes ini, indeks yang dipesan secara rawak ialah ID dokumen.

    Kemudian dalam bahagian pertanyaan kami, nilai rawak yang anda hasilkan ialah ID automatik baharu (iOS, Android, Web), medan yang anda tanya ialah medan __name__ dan nilai rendah 'disebut kemudian' ialah rentetan kosong. Ini adalah cara paling mudah untuk menjana indeks rawak, dan akan berfungsi tanpa mengira bahasa dan platform.

    Secara lalai, nama dokumen (__name__) 仅按升序索引,并且除了删除和重新创建之外,您也无法重命名现有文档。如果您需要其中任何一个,您仍然可以使用此方法,只需将自动 ID 存储为名为 random) hanya diindeks dalam tertib menaik, dan anda juga tidak boleh menamakan semula dokumen sedia ada kecuali dengan memadam dan menciptanya semula. Jika anda memerlukan salah satu daripada ini, anda masih boleh menggunakan kaedah ini, hanya simpan ID automatik sebagai medan sebenar bernama

    dan bukannya membebankan nama dokumen untuk tujuan ini.

    Versi integer rawak

    randomApabila anda menulis dokumen, mula-mula jana integer rawak dalam julat terhad dan tetapkannya pada medan bernama

    . Bergantung pada bilangan dokumen yang anda jangkakan, anda boleh menggunakan julat sempadan yang berbeza untuk menjimatkan ruang atau mengurangkan risiko konflik (yang mengurangkan keberkesanan teknik ini).

    Anda harus mempertimbangkan bahasa yang anda perlukan kerana akan ada pertimbangan yang berbeza. Walaupun Swift mudah, JavaScript mempunyai masalah yang ketara: 🎜
    • integer 32-bit: sesuai untuk set data kecil (~10K tidak mungkin berlanggar)
    • integer 64-bit: set data besar (nota: tidak disokong oleh JavaScript itu sendiri, belum)

    Ini akan membuat indeks dengan dokumen diisih secara rawak. Kemudian dalam bahagian pertanyaan kami, nilai rawak yang anda hasilkan akan menjadi satu lagi daripada nilai ini dan "nilai rendah" yang disebut kemudian ialah -1.

    Bagaimana untuk menanyakan indeks rawak

    Sekarang anda mempunyai indeks rawak, anda perlu menanyakannya. Di bawah ini kita melihat beberapa variasi mudah yang memilih 1 dokumen rawak, serta pilihan untuk memilih berbilang 1 dokumen.

    Untuk semua pilihan ini, anda perlu menjana nilai rawak baharu dalam bentuk yang sama seperti nilai indeks yang anda buat semasa menulis dokumen, diwakili oleh pembolehubah random di bawah. Kami akan menggunakan nilai ini untuk mencari titik rawak pada indeks.

    Sarung

    Sekarang anda mempunyai nilai rawak, anda boleh menanyakan dokumen individu:

    let postsRef = db.collection("posts")
    queryRef = postsRef.whereField("random", isGreaterThanOrEqualTo: random)
                       .order(by: "random")
                       .limit(to: 1)

    Semak sama ada dokumen telah dikembalikan. Jika tidak, tanya semula, tetapi dengan "nilai rendah" indeks rawak. Contohnya, jika anda melakukan integer rawak, maka lowValue0:

    let postsRef = db.collection("posts")
    queryRef = postsRef.whereField("random", isGreaterThanOrEqualTo: lowValue)
                       .order(by: "random")
                       .limit(to: 1)

    Selagi anda mempunyai satu dokumen, anda dijamin akan memulangkan sekurang-kurangnya 1 dokumen.

    Kedua-dua arah

    Kaedah balut mudah dilaksanakan dan membolehkan anda mengoptimumkan storan dengan hanya pengindeksan menaik didayakan. Satu kelemahan ialah nilai mungkin dilindungi secara tidak adil. Sebagai contoh, jika 3 dokumen pertama dalam 10K (A, B, C) mempunyai nilai indeks rawak A:409496, B:436496, C:818992, maka peluang A dan C dipilih adalah kurang daripada 1/10K , manakala B akan dipilih kerana A terlindung dengan berkesan dari jarak dekat, dan hanya mempunyai kira-kira 1/160K peluang.

    Anda boleh memilih secara rawak antara >=<=Daripada membuat pertanyaan sehala dan membungkus apabila nilai tidak ditemui, ini mengurangkan kebarangkalian menutup nilai secara tidak adil sebanyak separuh dengan kos menggandakan storan indeks.

    Jika tiada hasil dikembalikan ke satu arah, tukar ke arah lain:

    queryRef = postsRef.whereField("random", isLessThanOrEqualTo: random)
                       .order(by: "random", descending: true)
                       .limit(to: 1)
    
    queryRef = postsRef.whereField("random", isGreaterThanOrEqualTo: random)
                       .order(by: "random")
                       .limit(to: 1)

    Pilih berbilang dokumen rawak

    Biasanya, anda perlu memilih berbilang dokumen rawak sekaligus. Terdapat dua cara berbeza untuk menyesuaikan teknik di atas bergantung pada pertukaran yang anda inginkan.

    Bilas dan ulang

    Kaedah ini sangat mudah. Hanya ulangi proses, termasuk memilih integer rawak baharu setiap kali.

    Kaedah ini akan memberikan anda urutan rawak dokumen tanpa perlu risau melihat corak yang sama berulang kali.

    Pertukarannya ialah ia akan menjadi lebih perlahan daripada kaedah seterusnya kerana ia memerlukan perjalanan pergi balik yang berasingan untuk menyampaikan setiap dokumen.

    Teruskan

    Dalam kaedah ini, hanya menambah had bilangan dokumen yang diperlukan. Ini agak rumit kerana anda mungkin memulangkan 0..limit dokumen dalam panggilan. Kemudian anda perlu mendapatkan dokumen yang hilang dengan cara yang sama, tetapi dengan batasan dikurangkan kepada hanya perbezaan. Jika anda tahu bahawa jumlah dokumen adalah lebih daripada yang anda minta, anda boleh mengoptimumkan dengan mengabaikan kes tepi di mana dokumen yang mencukupi tidak pernah diambil pada panggilan kedua (tetapi bukan yang pertama).

    Pertukaran dengan penyelesaian ini ialah urutan berulang. Walaupun dokumen diisih secara rawak, jika anda mempunyai julat bertindih, anda akan melihat corak yang sama yang anda lihat sebelum ini. Terdapat cara untuk mengurangkan kebimbangan ini, yang akan kita bincangkan dalam bahagian seterusnya mengenai pembenihan semula.

    Kaedah ini lebih pantas daripada "bilas dan ulangi" kerana anda akan meminta semua dokumen dalam satu panggilan dalam kes terbaik atau dua panggilan dalam kes terburuk.

    Reseed untuk rawak yang konsisten

    Walaupun kaedah ini akan memberikan anda dokumen secara rawak jika set dokumen adalah statik, kebarangkalian untuk mengembalikan setiap dokumen juga akan menjadi statik. Ini adalah masalah kerana sesetengah nilai mungkin mempunyai kebarangkalian yang sangat rendah atau tinggi bergantung pada nilai rawak awal yang diperoleh daripadanya. Dalam banyak kes penggunaan, ini baik, tetapi dalam sesetengahnya anda mungkin ingin meningkatkan kerawak jangka panjang supaya terdapat peluang yang lebih genap untuk mana-mana 1 dokumen dikembalikan.

    Perhatikan bahawa dokumen yang dimasukkan akhirnya saling berkait di tengah, mengubah kebarangkalian secara beransur-ansur, dan perkara yang sama berlaku untuk dokumen yang dipadamkan. Jika kadar pemasukan/pemadaman terlalu kecil untuk bilangan dokumen tertentu, terdapat beberapa strategi untuk menyelesaikan masalah ini.

    Rawak berbilang

    Anda tidak perlu risau tentang pembenihan semula, anda sentiasa boleh membuat berbilang indeks rawak setiap dokumen dan memilih salah satu daripadanya secara rawak setiap kali. Contohnya, biarkan medan random menjadi peta yang mengandungi subbidang 1 hingga 3:

    {'random': {'1': 32456, '2':3904515723, '3': 766958445}}

    Kini anda secara rawak akan bertanya secara rawak.1, rawak.2, rawak.3, mewujudkan taburan rawak yang lebih besar. Ini pada asasnya menggunakan ruang storan yang lebih besar untuk menjimatkan pengiraan yang meningkat (penulisan dokumen) pembenihan semula.

    Reseed sambil menulis

    Setiap kali dokumen dikemas kini, nilai rawak untuk medan random akan dijana semula. Ini akan mengalihkan dokumen dalam indeks rawak.

    Menyemai semula semasa dibaca

    Jika nilai rawak yang dijana tidak diagihkan secara sama rata (ia adalah rawak, jadi ini dijangka), dokumen yang sama boleh dipilih pada masa yang tidak sesuai. Masalah ini boleh diselesaikan dengan mudah dengan mengemas kini dokumen yang dipilih secara rawak dengan nilai rawak baharu selepas membacanya.

    Memandangkan penulisan lebih mahal dan boleh menjadi tempat liputan, anda boleh memilih untuk mengemas kini hanya pada subset masa baca (cth. if random(0,100) === 0) update;). < /p>

    balas
    0
  • Batalbalas