Google Firestore: query sulla sottostringa di un valore di proprietà (ricerca di testo)


104

Sto cercando di aggiungere un semplice campo di ricerca, vorrei usare qualcosa di simile

collectionRef.where('name', 'contains', 'searchTerm')

Ho provato a usare where('name', '==', '%searchTerm%'), ma non ha restituito nulla.


2
per favore hai trovato qualche soluzione. Ho cercato per giorni qualcosa di simile senza alcuna mancanza
suulisin

1
Firebase ora lo supporta. Si prega di aggiornare la risposta: stackoverflow.com/a/52715590/2057171
Albert Renshaw

1
Penso che il modo migliore sia creare uno script che indicizzi manualmente ogni documento. Quindi interroga quegli indici. controlla questo: angularfirebase.com/lessons/…
Kiblawi_Rabee

Risposte:


35

Non c'è tale operatore, quelli ammessi sono ==, <, <=, >, >=.

Puoi filtrare solo per prefissi, ad esempio per tutto ciò che inizia tra bare fooche puoi utilizzare

collectionRef.where('name', '>=', 'bar').where('name', '<=', 'foo')

Puoi utilizzare servizi esterni come Algolia o ElasticSearch per questo.


5
Non è proprio quello che sto cercando. Ho un ampio elenco di prodotti con titoli lunghi. "Rebok Mens Tennis Racket". Un utente potrebbe cercare tennis, ma in base agli operatori di query disponibili non c'è modo di ottenere quei risultati. Combinando >=e <=non funziona. Ovviamente posso usare l'Algolia, ma potrei anche usarlo con Firebase per fare la maggior parte delle query e non è necessario passare a Firestore ...
tehfailsafe

4
@tehfailsafe Bene, la tua domanda è "come interrogare se un campo contiene una stringa" e la risposta è "non puoi farlo".
Kuba

20
@ A.Chakroun che cosa è esattamente scortese nella mia risposta?
Kuba

18
tbh questo è qualcosa di veramente necessario. Non riesco a capire perché la squadra di Firebase non ci abbia pensato
Dani

2
Davvero sorprendente che Firebase sia così debole nelle query. Non riesco a credere che ci siano così tante persone che lo stanno usando se non è in grado di supportare una query così semplice.
Bagusflyer

43

Sebbene la risposta di Kuba sia vera per quanto riguarda le restrizioni, puoi emularla parzialmente con una struttura simile a un set:

{
  'terms': {
    'reebok': true,
    'mens': true,
    'tennis': true,
    'racket': true
  }
}

Ora puoi eseguire query con

collectionRef.where('terms.tennis', '==', true)

Questo funziona perché Firestore creerà automaticamente un indice per ogni campo. Sfortunatamente questo non funziona direttamente per le query composte perché Firestore non crea automaticamente indici compositi.

Puoi ancora aggirare questo problema memorizzando combinazioni di parole, ma diventa brutto velocemente.

Probabilmente stai ancora meglio con una ricerca full text fuoribordo .


È possibile utilizzare la funzione cloud con cloud.google.com/appengine/docs/standard/java/search ?
Henry

1
Se lo stai chiedendo come seguito a questa risposta, allora: la ricerca full text di AppEngine è completamente separata da Firestore e quindi questo non ti aiuterà direttamente. È possibile replicare i dati utilizzando una funzione cloud, ma questo è essenzialmente il suggerimento di utilizzare la ricerca full-text esterna. Se stai chiedendo qualcos'altro, inizia una nuova domanda.
Gil Gilbert

1
In Firestore, è necessario indicizzare tutti i termini prima dell'usowhere
Husam

4
Come accennato da Husam, tutti questi campi dovrebbero essere indicizzati. Volevo abilitare la ricerca per qualsiasi termine contenuto nel nome del mio prodotto. Quindi ho creato una proprietà di tipo 'oggetto' sul mio documento con le chiavi che fanno parte del nome del prodotto, ognuna con il valore 'true' assegnato ad essa, sperando che la ricerca dove ('nameSegments.tennis', '==', true) sarebbe work, ma firestore suggerisce di creare un indice per nameSegments.tennis, lo stesso per ogni altro termine. Poiché può esserci un numero infinito di termini, questa risposta è utilizzabile solo per uno scennario molto limitato quando tutti i termini di ricerca sono definiti in anticipo.
Slawoj

2
@epeleg La query funzionerebbe, dopo aver creato un indice per esso, tuttavia non è possibile creare un indice per ogni possibile termine contenuto nel nome del prodotto, quindi per la ricerca testuale dei termini nei nomi dei prodotti questo approccio non ha funzionato nel mio caso.
Slawoj

43

Sono d'accordo con la risposta di @ Kuba, ma ancora, è necessario aggiungere una piccola modifica per funzionare perfettamente per la ricerca per prefisso. ecco cosa ha funzionato per me

Per la ricerca di record che iniziano con il nome queryText

collectionRef.where('name', '>=', queryText).where('name', '<=', queryText+ '\uf8ff').

Il carattere \uf8ffutilizzato nella query è un punto di codice molto alto nell'intervallo Unicode (è un codice area di utilizzo privato [PUA]). Poiché è dopo la maggior parte dei caratteri regolari in Unicode, la query corrisponde a tutti i valori che iniziano con queryText.


1
Buona risposta !, funziona benissimo per la ricerca del testo del prefisso. Per cercare parole nel testo, provare l'implementazione "array-contains" come spiegato in questo post medium.com/@ken11zer01/…
guillefd

Sto solo pensando, ma in teoria potresti abbinare tutti i valori che terminano con queryTest creando un altro campo e invertendo i dati ...
Jonathan

Sì @ Jonathan, anche questo è possibile.
Ankit Prajapati

30

Sebbene Firebase non supporti esplicitamente la ricerca di un termine all'interno di una stringa,

Firebase (ora) supporta quanto segue che risolverà il tuo caso e molti altri:

A partire da agosto 2018 supportano le array-containsquery. Vedi: https://firebase.googleblog.com/2018/08/better-arrays-in-cloud-firestore.html

È ora possibile impostare tutti i termini chiave in un array come un campo, quindi eseguire una query per tutti i documenti che hanno un array che contiene "X". È possibile utilizzare AND logico per effettuare ulteriori confronti per query aggiuntive. (Questo perché firebase attualmente non supporta in modo nativo le query composte per più query contenenti array, quindi le query di ordinamento "AND" dovranno essere eseguite sul client)

L'uso di array in questo stile consentirà loro di essere ottimizzati per scritture simultanee, il che è bello! Non ho verificato che supporti le richieste batch (i documenti non lo dicono) ma scommetto che lo fa poiché è una soluzione ufficiale.


Utilizzo:

collection("collectionPath").
    where("searchTermsArray", "array-contains", "term").get()

12
Questa è una bella soluzione. Tuttavia, correggimi se sbaglio, ma penso che non ti permetta di fare ciò che @tehfailsafe ha chiesto. Ad esempio, se vuoi ottenere tutti i nomi che contengono la stringa "abc", non otterrai alcun successo con array-contains, poiché restituirà solo i documenti che hanno il nome esatto di "abc", ma "abcD" o "0abc" sarebbe fuori.
Yulian

1
@Yulian Nel mondo della programmazione, Search termsi intende tipicamente un termine intero separato da spazio, punteggiatura, ecc. Su entrambi i lati. Se utilizzi Google in abcdequesto momento, troverai solo risultati per cose come %20abcde.o ,abcde!ma non abcdefghijk... anche se sicuramente l'intero alfabeto digitato è molto più comune su Internet, la ricerca non è per abcde * è per un abcde isolato
Albert Renshaw

1
Capisco il tuo punto e sono d'accordo, ma probabilmente sono stato fuorviato dalla parola 'contains', che significa esattamente ciò a cui mi riferisco in molti linguaggi di programmazione. Lo stesso vale '%searchTerm%'da un punto di vista SQL.
Yulian

2
@ Yulian Sì, ho capito. Firebase è NoSQL, quindi è davvero bravo a rendere questi tipi di operazioni veloci ed efficienti, anche se possono essere limitati per alcuni problemi fuori ambito come la ricerca di stringhe con caratteri jolly.
Albert Renshaw

2
Bene, potresti creare un campo separato per ognuno con la rappresentazione delle parole divise come titleArray: ['this', 'is', 'a', 'title'] ogni volta che aggiorni il documento. E poi la ricerca sarà basata su quel campo invece che sul titolo. Si crea a freddo un triiger onUpdate per creare questi campi. Molto lavoro per il testo basato sulla ricerca, ma preferisco i miglioramenti delle prestazioni di NoSQL.
sfratini

14

Secondo i documenti di Firestore , Cloud Firestore non supporta l'indicizzazione nativa o la ricerca di campi di testo nei documenti. Inoltre, scaricare un'intera raccolta per cercare i campi lato client non è pratico.

Si consigliano soluzioni di ricerca di terze parti come Algolia ed Elastic Search .


46
Ho letto i documenti, anche se non è l'ideale. Lo svantaggio è che Algolia e Firestore hanno diversi modelli di prezzo ... Posso tranquillamente avere 600.000 documenti in Firestore (purché non ne interroghi troppi al giorno). Quando li spingo in Algolia per cercare, ora devo pagare all'Algolia $ 310 al mese solo per poter fare una ricerca per titolo sui miei documenti Firestore.
tehfailsafe

2
il problema è che questo non è gratuito
Dani

Questa è la risposta corretta alla domanda posta e dovrebbe essere accettata come la migliore.
briznad

11

Alcune note qui:

1.) \uf8ff funziona allo stesso modo di~

2.) È possibile utilizzare una clausola where o clausole start end:

ref.orderBy('title').startAt(term).endAt(term + '~');

è esattamente lo stesso di

ref.where('title', '>=', term).where('title', '<=', term + '~');

3.) No, non funziona se inverti startAt()e endAt()in ogni combinazione, tuttavia, puoi ottenere lo stesso risultato creando un secondo campo di ricerca che viene invertito e combinando i risultati.

Esempio: per prima cosa devi salvare una versione invertita del campo quando il campo viene creato. Qualcosa come questo:

// collection
const postRef = db.collection('posts')

async function searchTitle(term) {

  // reverse term
  const termR = term.split("").reverse().join("");

  // define queries
  const titles = postRef.orderBy('title').startAt(term).endAt(term + '~').get();
  const titlesR = postRef.orderBy('titleRev').startAt(termR).endAt(termR + '~').get();

  // get queries
  const [titleSnap, titlesRSnap] = await Promise.all([
    titles,
    titlesR
  ]);
  return (titleSnap.docs).concat(titlesRSnap.docs);
}

Con questo, puoi cercare le ultime lettere di un campo stringa e le prime , solo lettere centrali o gruppi di lettere casuali. Questo è più vicino al risultato desiderato. Tuttavia, questo non ci aiuterà davvero quando vogliamo lettere o parole centrali casuali. Inoltre, ricorda di salvare tutto in minuscolo o una copia minuscola per la ricerca, quindi le maiuscole non saranno un problema.

4.) Se hai solo poche parole, il Metodo di Ken Tan farà tutto quello che vuoi, o almeno dopo averlo leggermente modificato. Tuttavia, con solo un paragrafo di testo, creerai in modo esponenziale più di 1 MB di dati, che è maggiore del limite di dimensioni del documento di firestore (lo so, l'ho testato).

5.) Se potessi combinare array-contains (o qualche forma di array) con il \uf8fftrucco, potresti avere una ricerca praticabile che non raggiunge i limiti. Ho provato ogni combinazione, anche con le mappe, e un no go. Se qualcuno lo capisce, pubblicalo qui.

6.) Se devi allontanarti da ALGOLIA e ELASTIC SEARCH, e non ti biasimo affatto, potresti sempre usare mySQL, postSQL o neo4Js su Google Cloud. Sono tutti e 3 facili da configurare e hanno livelli gratuiti. Avresti una funzione cloud per salvare i dati suCreate () e un'altra funzione onCall () per cercare i dati. Semplice ... ish. Allora perché non passare a mySQL? I dati in tempo reale ovviamente! Quando qualcuno scrive DGraph con websocks per dati in tempo reale, contami!

Algolia ed ElasticSearch sono stati creati per essere dbs di sola ricerca, quindi non c'è niente di così veloce ... ma paghi per questo. Google, perché ci allontani da Google e non segui MongoDB noSQL e consenti le ricerche?

AGGIORNAMENTO - HO CREATO UNA SOLUZIONE:

https://fireblog.io/blog/post/firestore-full-text-search


Un'ottima panoramica e molto utile.
RedFilter

Eccezionale! upvote per una risposta ben strutturata e informativa.
King Of The Jungle,

10

Risposta tardiva ma per chiunque stia ancora cercando una risposta, diciamo che abbiamo una raccolta di utenti e in ogni documento della raccolta abbiamo un campo "nome utente", quindi se vuoi trovare un documento in cui il nome utente inizia con "al" possiamo fare qualcosa di simile

 FirebaseFirestore.getInstance().collection("users").whereGreaterThanOrEqualTo("username", "al")

questa è un'ottima soluzione facile grazie. Ma cosa succede se si desidera controllare più di un campo. Come "nome" e "descrizione" collegati da un OR?
Provalo il

Non credo che si può query basata su due campi, purtroppo Firebase è male quando si tratta di esecuzione di query, è possibile controllare questa speranza aiuta stackoverflow.com/questions/26700924/...
MoTahir

1
Confermato, @MoTahir. Non c'è "OR" in Firestore.
Rap

quella soluzione non corrisponde ai nomi utente che iniziano con "al" ... ad esempio "hello" verrebbe abbinato ("hello"> "al")
antoine129,

L'interrogazione tramite OR è semplicemente una questione di combinazione di due risultati di ricerca. Ordinare questi risultati è un problema diverso ...
Jonathan

7

Sono sicuro che Firebase uscirà presto con "string-contains" per catturare qualsiasi index [i] startAt nella stringa ... Ma ho cercato sul web e ho trovato questa soluzione pensata da qualcun altro che ha impostato i tuoi dati come Questo

state = {title:"Knitting"}
...
const c = this.state.title.toLowerCase()

var array = [];
for (let i = 1; i < c.length + 1; i++) {
 array.push(c.substring(0, i));
}

firebase
.firestore()
.collection("clubs")
.doc(documentId)
.update({
 title: this.state.title,
 titleAsArray: array
})

inserisci qui la descrizione dell'immagine

query come questa

firebase
.firestore()
.collection("clubs")
.where(
 "titleAsArray",
 "array-contains",
 this.state.userQuery.toLowerCase()
)

Non consigliato affatto. Poiché i documenti hanno un limite di 20k righe, quindi non puoi utilizzarli in questo modo, finché non sei sicuro che il tuo documento non raggiungerà mai tali limiti
Sandeep

È l'opzione migliore al momento, cos'altro è consigliato?
Nick Carducci

1
@Sandeep Sono abbastanza sicuro che la dimensione sia limitata a 1 MB di dimensione e 20 livelli di profondità per documento. Cosa intendi per 20k linee? Questa è attualmente la soluzione migliore se utilizzare Algolia o ElasticSearch è fuori dal tavolo
ppicom

5

Se non desideri utilizzare un servizio di terze parti come l'Algolia, Firebase Cloud Functions è un'ottima alternativa. È possibile creare una funzione che possa ricevere un parametro di input, elaborare i record lato server e quindi restituire quelli che corrispondono ai criteri.


1
E per quanto riguarda Android?
Pratik Butani

Stai proponendo alle persone di iterare su ogni singolo record di una raccolta?
DarkNeuron

Non proprio. Userei Array.prototype. * - Come .every (), .some (), .map (), .filter (), ecc. Questo viene fatto in Node sul server in una funzione Firebase prima di restituire i valori al cliente.
Rap

3
Dovresti comunque leggere TUTTI i documenti per cercarli, il che comporta delle spese ed è costoso per il tempo.
Jonathan

3

In realtà penso che la soluzione migliore per farlo all'interno di Firestore sia inserire tutte le sottostringhe in un array e fare semplicemente una query array_contains. Ciò consente di eseguire la corrispondenza delle sottostringhe. Un po 'eccessivo per memorizzare tutte le sottostringhe, ma se i termini di ricerca sono brevi è molto ragionevole.


2

Ho appena avuto questo problema e ho trovato una soluzione piuttosto semplice.

String search = "ca";
Firestore.instance.collection("categories").orderBy("name").where("name",isGreaterThanOrEqualTo: search).where("name",isLessThanOrEqualTo: search+"z")

IsG majorThanOrEqualTo ci consente di filtrare l'inizio della nostra ricerca e aggiungendo una "z" alla fine di isLessThanOrEqualTo chiudiamo la nostra ricerca per non passare ai documenti successivi.


3
Ho provato questa soluzione ma per me funziona solo quando viene inserita la stringa completa. Ad esempio, se voglio ottenere il termine "gratuito", se inizio a digitare "fr" non verrà restituito nulla. Una volta digitato "libero", il termine mi fornisce la sua istantanea.
Chris

Stai usando lo stesso formato di codice? E il termine è una stringa in Firestore? So che non puoi filtrare in base a documentId.
Jacob Bonk,

2

La risposta selezionata funziona solo per le ricerche esatte e non è un comportamento di ricerca naturale dell'utente (la ricerca di "mela" in "Joe ha mangiato una mela oggi" non funzionerebbe).

Penso che la risposta di Dan Fein sopra dovrebbe essere classificata più in alto. Se i dati della stringa che stai cercando sono brevi, puoi salvare tutte le sottostringhe della stringa in un array nel tuo documento e quindi cercare nell'array con la query array_contains di Firebase. I documenti Firebase sono limitati a 1 MiB (1.048.576 byte) ( quote e limiti di Firebase ), che corrisponde a circa 1 milione di caratteri salvati in un documento (penso 1 carattere ~ = 1 byte). Memorizzare le sottostringhe va bene fintanto che il documento non è vicino a 1 milione di segni.

Esempio per cercare nomi utente:

Passaggio 1: aggiungi la seguente estensione String al tuo progetto. Ciò consente di suddividere facilmente una stringa in sottostringhe. (L' ho trovato qui ).

extension String {

var length: Int {
    return count
}

subscript (i: Int) -> String {
    return self[i ..< i + 1]
}

func substring(fromIndex: Int) -> String {
    return self[min(fromIndex, length) ..< length]
}

func substring(toIndex: Int) -> String {
    return self[0 ..< max(0, toIndex)]
}

subscript (r: Range<Int>) -> String {
    let range = Range(uncheckedBounds: (lower: max(0, min(length, r.lowerBound)),
                                        upper: min(length, max(0, r.upperBound))))
    let start = index(startIndex, offsetBy: range.lowerBound)
    let end = index(start, offsetBy: range.upperBound - range.lowerBound)
    return String(self[start ..< end])
}

Passaggio 2: quando si memorizza il nome di un utente, memorizzare anche il risultato di questa funzione come un array nello stesso documento. Questo crea tutte le variazioni del testo originale e le memorizza in un array. Ad esempio, l'input di testo "Apple" creerebbe il seguente array: ["a", "p", "p", "l", "e", "ap", "pp", "pl", "le "," app "," ppl "," ple "," appl "," pple "," apple "], che dovrebbero comprendere tutti i criteri di ricerca che un utente potrebbe inserire. Puoi lasciare maximumStringSize come zero se vuoi tutti i risultati, tuttavia, se c'è un testo lungo, ti consiglio di limitarlo prima che la dimensione del documento diventi troppo grande - da qualche parte circa 15 funziona bene per me (la maggior parte delle persone non cerca comunque frasi lunghe ).

func createSubstringArray(forText text: String, maximumStringSize: Int?) -> [String] {

    var substringArray = [String]()
    var characterCounter = 1
    let textLowercased = text.lowercased()

    let characterCount = text.count
    for _ in 0...characterCount {
        for x in 0...characterCount {
            let lastCharacter = x + characterCounter
            if lastCharacter <= characterCount {
                let substring = textLowercased[x..<lastCharacter]
                substringArray.append(substring)
            }
        }
        characterCounter += 1

        if let max = maximumStringSize, characterCounter > max {
            break
        }
    }

    print(substringArray)
    return substringArray
}

Passaggio 3: puoi utilizzare la funzione array_contains di Firebase!

[yourDatabasePath].whereField([savedSubstringArray], arrayContains: searchText).getDocuments....

0

Con Firestore puoi implementare una ricerca full text ma costerà comunque più letture di quanto non avrebbe altrimenti, e inoltre dovrai inserire e indicizzare i dati in un modo particolare, quindi in questo approccio puoi utilizzare le funzioni cloud di Firebase per tokenize e quindi hash il testo di input mentre si sceglie una funzione hash lineare h(x)che soddisfi quanto segue - if x < y < z then h(x) < h (y) < h(z). Per la tokenizzazione puoi scegliere alcune librerie NLP leggere per mantenere basso il tempo di avvio a freddo della tua funzione che può eliminare le parole non necessarie dalla tua frase. Quindi puoi eseguire una query con l'operatore minore di e maggiore di in Firestore. Durante la memorizzazione anche dei dati, dovrai assicurarti di eseguire l'hash del testo prima di memorizzarlo e memorizzare il testo normale anche come se cambiassi il testo normale, anche il valore con hash cambierà.


0

Questo ha funzionato perfettamente per me, ma potrebbe causare problemi di prestazioni.

Fai questo quando esegui una query su Firestore:

   Future<QuerySnapshot> searchResults = collectionRef
        .where('property', isGreaterThanOrEqualTo: searchQuery.toUpperCase())
        .getDocuments();

Fallo nel tuo FutureBuilder:

    return FutureBuilder(
          future: searchResults,
          builder: (context, snapshot) {           
            List<Model> searchResults = [];
            snapshot.data.documents.forEach((doc) {
              Model model = Model.fromDocumet(doc);
              if (searchQuery.isNotEmpty &&
                  !model.property.toLowerCase().contains(searchQuery.toLowerCase())) {
                return;
              }

              searchResults.add(model);
            })
   };

0

Ad oggi, ci sono fondamentalmente 3 diverse soluzioni alternative, che sono state suggerite dagli esperti, come risposte alla domanda.

Li ho provati tutti. Ho pensato che potesse essere utile documentare la mia esperienza con ognuno di loro.

Metodo-A: utilizzo di: (dbField "> =" searchString) & (dbField "<=" searchString + "\ uf8ff")

Suggerito da @Kuba e @Ankit Prajapati

.where("dbField1", ">=", searchString)
.where("dbField1", "<=", searchString + "\uf8ff");

A.1 Le query Firestore possono eseguire solo filtri di intervallo (>, <,> =, <=) su un singolo campo. Le query con filtri di intervallo su più campi non sono supportate. Utilizzando questo metodo, non è possibile avere un operatore di intervallo in nessun altro campo del database, ad esempio un campo data.

A.2. Questo metodo NON funziona per la ricerca in più campi contemporaneamente. Ad esempio, non puoi controllare se una stringa di ricerca è in uno dei campi (nome, note e indirizzo).

Metodo B: utilizzo di una MAP delle stringhe di ricerca con "true" per ciascuna voce nella mappa e utilizzo dell'operatore "==" nelle query

Suggerito da @Gil Gilbert

document1 = {
  'searchKeywordsMap': {
    'Jam': true,
    'Butter': true,
    'Muhamed': true,
    'Green District': true,
    'Muhamed, Green District': true,
  }
}

.where(`searchKeywordsMap.${searchString}`, "==", true);

B.1 Ovviamente, questo metodo richiede un'elaborazione aggiuntiva ogni volta che i dati vengono salvati nel db e, cosa più importante, richiede spazio aggiuntivo per memorizzare la mappa delle stringhe di ricerca.

B.2 Se una query Firestore ha una singola condizione come quella sopra, non è necessario creare alcun indice in anticipo. Questa soluzione funzionerebbe perfettamente in questo caso.

B.3 Tuttavia, se la query ha un'altra condizione, ad esempio (status === "active",) sembra che sia richiesto un indice per ogni "stringa di ricerca" inserita dall'utente. In altre parole, se un utente cerca "Jam" e un altro utente cerca "Butter", è necessario creare prima un indice per la stringa "Jam" e un altro per "Butter", ecc. A meno che tu non possa prevedere tutto il possibile stringhe di ricerca degli utenti, questo NON funziona - nel caso in cui la query abbia altre condizioni!

.where(searchKeywordsMap["Jam"], "==", true); // requires an index on searchKeywordsMap["Jam"]
.where("status", "==", "active");

** Metodo-C: utilizzo di un ARRAY di stringhe di ricerca e dell'operatore "array-contains"

Suggerito da @Albert Renshaw e dimostrato da @Nick Carducci

document1 = {
  'searchKeywordsArray': [
    'Jam',
    'Butter',
    'Muhamed',
    'Green District',
    'Muhamed, Green District',
  ]
}

.where("searchKeywordsArray", "array-contains", searchString); 

C.1 Simile al Metodo-B, questo metodo richiede un'elaborazione aggiuntiva ogni volta che i dati vengono salvati nel database e, cosa più importante, richiede spazio aggiuntivo per memorizzare l'array di stringhe di ricerca.

C.2 Le query Firestore possono includere al massimo una clausola "array-contains" o "array-contains-any" in una query composta.

Limitazioni generali:

  1. Nessuna di queste soluzioni sembra supportare la ricerca di stringhe parziali. Ad esempio, se un campo db contiene "1 Peter St, Green District", non è possibile cercare la stringa "strict".
  2. È quasi impossibile coprire tutte le possibili combinazioni di stringhe di ricerca previste. Ad esempio, se un campo db contiene "1 Mohamed St, Green District", potresti NON essere in grado di cercare la stringa "Green Mohamed", che è una stringa con le parole in un ordine diverso dall'ordine utilizzato nel db campo.

Non esiste una soluzione che vada bene per tutti. Ogni soluzione alternativa ha i suoi limiti. Spero che le informazioni di cui sopra possano aiutarti durante il processo di selezione tra queste soluzioni alternative.

Per un elenco delle condizioni delle query Firestore, consulta la documentazione https://firebase.google.com/docs/firestore/query-data/queries .

Non ho provato https://fireblog.io/blog/post/firestore-full-text-search , che è suggerito da @Jonathan.


-10

Possiamo usare il back-tick per stampare il valore di una stringa. Questo dovrebbe funzionare:

where('name', '==', `${searchTerm}`)

Grazie, ma questa domanda riguarda l'ottenimento di valori non esatti. Ad esempio, l'esempio in questione funziona per trovare se il nome è esatto. Se ho un documento con nome: "Test" e poi cerco "Test", funziona. Ma mi aspetto di essere in grado di cercare "tes" o "est" e ottenere comunque il risultato "Test". Immagina un caso d'uso con i titoli dei libri. Le persone spesso cercano titoli di libri parziali anziché interamente il titolo preciso.
tehfailsafe

13
@suulisin hai ragione, non l'ho letto attentamente perché ero ansioso di condividere ciò che avevo trovato. Grazie per il tuo impegno nel sottolinearlo e starò più attento
Zach J
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.