Rumah > Soal Jawab > teks badan
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粉6681137682023-10-20 09:51:55
Menyiarkan ini untuk membantu sesiapa sahaja yang menghadapi isu ini pada masa hadapan.
Jika anda menggunakan auto-ID, anda boleh menjana auto-ID baharu dan menanyakan auto-ID yang paling hampir, seperti dalam Jawapan Dan McGrath<中所述< /a>.
Saya baru-baru ini mencipta api petikan rawak yang perlu mendapatkan petikan rawak daripada koleksi firestore.
Beginilah cara saya menyelesaikan masalah ini:
var db = admin.firestore(); var quotes = db.collection("quotes"); var key = quotes.doc().id; quotes.where(admin.firestore.FieldPath.documentId(), '>=', key).limit(1).get() .then(snapshot => { if(snapshot.size > 0) { snapshot.forEach(doc => { console.log(doc.id, '=>', doc.data()); }); } else { var quote = quotes.where(admin.firestore.FieldPath.documentId(), '<', key).limit(1).get() .then(snapshot => { snapshot.forEach(doc => { console.log(doc.id, '=>', doc.data()); }); }) .catch(err => { console.log('Error getting documents', err); }); } }) .catch(err => { console.log('Error getting documents', err); });
Kunci kepada pertanyaan adalah ini:
.where(admin.firestore.FieldPath.documentId(), '>', key)
Jika tiada dokumen ditemui, hubungi semula dengan operasi yang bertentangan.
Semoga ini membantu!
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:
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.
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
random
Apabila anda menulis dokumen, mula-mula jana integer rawak dalam julat terhad dan tetapkannya pada medan bernama
Anda harus mempertimbangkan bahasa yang anda perlukan kerana akan ada pertimbangan yang berbeza. Walaupun Swift mudah, JavaScript mempunyai masalah yang ketara: 🎜
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.
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.
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 lowValue
为 0
:
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.
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)
Biasanya, anda perlu memilih berbilang dokumen rawak sekaligus. Terdapat dua cara berbeza untuk menyesuaikan teknik di atas bergantung pada pertukaran yang anda inginkan.
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.
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.
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.
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.
Setiap kali dokumen dikemas kini, nilai rawak untuk medan random
akan dijana semula. Ini akan mengalihkan dokumen dalam indeks rawak.
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>