Google Firestore: Abfrage zur Teilzeichenfolge eines Eigenschaftswerts (Textsuche)

103

Ich möchte ein einfaches Suchfeld hinzufügen, möchte so etwas wie verwenden

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

Ich habe es versucht where('name', '==', '%searchTerm%'), aber es hat nichts zurückgegeben.

tehfailsafe
quelle
2
Bitte haben Sie eine Lösung gefunden. Ich habe seit Tagen nach etwas Ähnlichem ohne Mangel
gesucht
1
Firebase unterstützt dies jetzt. Bitte aktualisieren Sie die Antwort: stackoverflow.com/a/52715590/2057171
Albert Renshaw
1
Ich denke, der beste Weg ist, ein Skript zu erstellen, das jedes Dokument manuell indiziert. Fragen Sie dann diese Indizes ab. Überprüfen Sie dies heraus: angularfirebase.com/lessons/…
Kiblawi_Rabee

Antworten:

34

Es gibt keine solche Betreiber, erlaubt diejenigen sind ==, <, <=, >, >=.

Sie können nur nach Präfixen filtern, z. B. nach allem, was dazwischen beginnt barund was fooSie verwenden können

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

Sie können dafür externe Dienste wie Algolia oder ElasticSearch verwenden.

Kuba
quelle
5
Das ist nicht ganz das, wonach ich suche. Ich habe eine große Liste von Produkten mit langen Titeln. "Rebok Herren Tennisschläger". Ein Benutzer sucht möglicherweise nach tennis, aber basierend auf den verfügbaren Abfrageoperatoren gibt es keine Möglichkeit, diese Ergebnisse zu erhalten. Kombinieren >=und <=funktioniert nicht. Natürlich kann ich Algolia verwenden, aber ich kann es auch einfach mit Firebase verwenden, um die meisten Abfragen zu erledigen, und muss nicht zum Firestore wechseln ...
tehfailsafe
4
@tehfailsafe Nun, Ihre Frage lautet "Wie kann man abfragen, ob ein Feld eine Zeichenfolge enthält?" und die Antwort lautet "Das können Sie nicht".
Kuba
20
@ A.Chakroun was genau ist unhöflich in meiner Antwort?
Kuba
16
Das ist etwas wirklich Notwendiges. Ich kann nicht verstehen, warum Firebases Team nicht darüber nachgedacht hat
Dani
2
Wirklich überraschend, dass Firebase so schwach im Abfragen ist. Ich kann nicht glauben, dass es so viele Leute gibt, die es verwenden, wenn es eine so einfache Abfrage nicht unterstützen kann.
Bagusflyer
43

Während Kubas Antwort in Bezug auf Einschränkungen wahr ist, können Sie dies teilweise mit einer satzartigen Struktur emulieren:

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

Jetzt können Sie mit abfragen

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

Dies funktioniert, da Firestore automatisch einen Index für jedes Feld erstellt. Leider funktioniert dies nicht direkt für zusammengesetzte Abfragen, da Firestore nicht automatisch zusammengesetzte Indizes erstellt.

Sie können dies immer noch umgehen, indem Sie Wortkombinationen speichern, aber dies wird schnell hässlich.

Mit einem Außenborder sind Sie wahrscheinlich immer noch besser dran Volltextsuche sind .

Gil Gilbert
quelle
Ist es möglich, die Cloud-Funktion mit cloud.google.com/appengine/docs/standard/java/search zu verwenden ?
Henry
1
Wenn Sie dies als Antwort auf diese Antwort fragen, dann: Die Volltextsuche von AppEngine ist völlig unabhängig von Firestore und hilft Ihnen daher nicht direkt. Sie können Ihre Daten mithilfe einer Cloud-Funktion replizieren. Dies ist jedoch im Wesentlichen der Vorschlag für die Verwendung der externen Volltextsuche. Wenn Sie etwas anderes fragen, beginnen Sie bitte eine neue Frage.
Gil Gilbert
1
In Firestore müssen Sie alle Begriffe indizieren, bevor Siewhere
Husam
4
Wie Husam erwähnte, müssten alle diese Felder indiziert werden. Ich wollte die Suche nach einem Begriff aktivieren, den mein Produktname enthält. Daher habe ich in meinem Dokument eine Eigenschaft vom Typ 'Objekt' erstellt, deren Schlüssel Teile des Produktnamens sind, denen jeweils der Wert 'true' zugewiesen ist, in der Hoffnung, dass bei der Suche nach ('nameSegments.tennis', '==', true) gesucht wird Arbeit, aber Firestore schlägt vor, einen Index für nameSegments.tennis zu erstellen, der für jeden anderen Begriff gleich ist. Da es unendlich viele Begriffe geben kann, kann diese Antwort nur für ein sehr begrenztes Szenario verwendet werden, wenn alle Suchbegriffe im Voraus definiert wurden.
Slawoj
2
@epeleg Die Abfrage würde funktionieren, nachdem Sie einen Index dafür erstellt haben. Es ist jedoch nicht möglich, einen Index für jeden möglichen Begriff zu erstellen, den Ihr Produktname enthält. Bei der Textsuche nach Begriffen in Produktnamen hat dieser Ansatz in meinem Fall nicht funktioniert.
Slawoj
42

Ich stimme der Antwort von @ Kuba zu. Dennoch muss eine kleine Änderung hinzugefügt werden, damit die Suche nach Präfix perfekt funktioniert. hier was für mich funktioniert hat

Zum Suchen von Datensätzen, die mit dem Namen beginnen queryText

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

Das \uf8ffin der Abfrage verwendete Zeichen ist ein sehr hoher Codepunkt im Unicode-Bereich (es handelt sich um einen PUA-Code (Private Usage Area)). Da die meisten regulären Zeichen in Unicode verwendet werden, stimmt die Abfrage mit allen Werten überein, die mit beginnen queryText.

Ankit Prajapati
quelle
1
Gute Antwort!, Dies funktioniert hervorragend für die Suche nach Präfixtext. Um nach Wörtern im Text zu suchen, versuchen Sie möglicherweise die Implementierung "Array-enthält", wie in diesem Beitrag erläutert. Medium.com/@ken11zer01/…
guillefd
Ich denke nur, aber theoretisch könnten Sie alle Werte, die mit queryTest enden, abgleichen, indem Sie ein anderes Feld erstellen und die Daten invertieren ...
Jonathan
Ja @Jonathan, das ist auch möglich.
Ankit Prajapati
30

Während Firebase die Suche nach einem Begriff innerhalb einer Zeichenfolge nicht explizit unterstützt,

Firebase unterstützt (jetzt) ​​Folgendes, das für Ihren Fall und viele andere gelöst werden kann:

Ab August 2018 unterstützen sie die array-containsAbfrage. Siehe: https://firebase.googleblog.com/2018/08/better-arrays-in-cloud-firestore.html

Sie können jetzt alle Schlüsselbegriffe in einem Array als Feld festlegen und dann alle Dokumente abfragen, deren Array 'X' enthält. Sie können das logische UND verwenden, um weitere Vergleiche für zusätzliche Abfragen durchzuführen. (Dies liegt daran, dass Firebase derzeit keine nativen zusammengesetzten Abfragen für mehrere Array-haltige Abfragen unterstützt, sodass die Sortierabfragen 'UND' auf Client-Seite durchgeführt werden müssen.)

Durch die Verwendung von Arrays in diesem Stil können sie für gleichzeitige Schreibvorgänge optimiert werden, was sehr hilfreich ist! Ich habe nicht getestet, ob es Batch-Anfragen unterstützt (Dokumente sagen es nicht), aber ich würde wetten, dass dies der Fall ist, da es eine offizielle Lösung ist.


Verwendung:

collection("collectionPath").
    where("searchTermsArray", "array-contains", "term").get()
Albert Renshaw
quelle
11
Dies ist eine schöne Lösung. Korrigieren Sie mich jedoch, wenn ich falsch liege, aber ich denke, es erlaubt Ihnen nicht, das zu tun, was @tehfailsafe verlangt hat. Wenn Sie beispielsweise alle Namen erhalten möchten, die die Zeichenfolge "abc" enthalten, werden Sie mit array-includes keinen Erfolg erzielen, da nur die Dokumente zurückgegeben werden, die den genauen Namen "abc", aber "abcD" oder "abcD" haben "0abc" wäre raus.
Yulian
1
@Yulian In der Programmierwelt Search termwird normalerweise ein ganzer Begriff verstanden, der auf beiden Seiten durch Leerzeichen, Interpunktion usw. getrennt ist. Wenn Sie abcdejetzt googeln, finden Sie nur Ergebnisse für Dinge wie %20abcde.oder ,abcde!aber nicht abcdefghijk... Auch wenn sicherlich das gesamte eingegebene Alphabet viel häufiger im Internet zu finden ist, wird nicht nach abcde * gesucht, sondern nach einem isolierten abcde
Albert Renshaw
1
Ich verstehe Ihren Standpunkt und stimme ihm zu, aber ich wurde wahrscheinlich durch das Wort irregeführt 'contains', was genau bedeutet, worauf ich mich in vielen Programmiersprachen beziehe. Gleiches gilt '%searchTerm%'aus SQL-Sicht.
Yulian
2
@ Yulian Ja, das verstehe ich. Firebase ist jedoch NoSQL, daher ist es wirklich gut, diese Arten von Vorgängen schnell und effizient zu gestalten, selbst wenn sie für einige Probleme außerhalb des Gültigkeitsbereichs wie die Suche nach Platzhalterstrings eingeschränkt sind.
Albert Renshaw
2
Nun, Sie können für jedes Feld ein eigenes Feld mit der Darstellung der Wörter erstellen, die wie titleArray aufgeteilt sind: ['this', 'is', 'a', 'title'] jedes Mal, wenn Sie das Dokument aktualisieren. Und dann basiert die Suche auf diesem Feld anstelle des Titels. Sie erstellen kalt ein Triiger onUpdate, um diese Felder zu erstellen. Viel Arbeit für suchbasierten Text, aber ich habe eher die Leistungsverbesserungen von NoSQL.
Sfratini
14

Gemäß den Firestore-Dokumenten unterstützt Cloud Firestore keine native Indizierung oder Suche nach Textfeldern in Dokumenten. Darüber hinaus ist das Herunterladen einer gesamten Sammlung zur clientseitigen Suche nach Feldern nicht praktikabel.

Suchlösungen von Drittanbietern wie Algolia und Elastic Search werden empfohlen.

bholben
quelle
45
Ich habe die Dokumente gelesen, obwohl es nicht ideal ist. Der Nachteil ist, dass Algolia und Firestore unterschiedliche Preismodelle haben ... Ich kann glücklich 600.000 Dokumente in Firestore haben (solange ich nicht zu viele pro Tag abfrage). Wenn ich sie zur Suche nach Algolia schiebe, muss ich Algolia jetzt 310 US-Dollar pro Monat zahlen, um eine Titelsuche in meinen Firestore-Dokumenten durchführen zu können.
ausfallsichere
2
Das Problem ist, dass dies nicht kostenlos ist
Dani
Dies ist die richtige Antwort auf die gestellte Frage und sollte als die beste akzeptiert werden.
Briznad
11

Ein paar Anmerkungen hier:

1.) \uf8ff funktioniert genauso wie~

2.) Sie können eine where-Klausel oder start end-Klauseln verwenden:

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

ist genau das gleiche wie

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

3.) Nein, es funktioniert nicht, wenn Sie umkehren startAt()und endAt()in jeder Kombination können Sie jedoch das gleiche Ergebnis erzielen, indem Sie ein zweites Suchfeld erstellen, das umgekehrt ist, und die Ergebnisse kombinieren.

Beispiel: Zuerst müssen Sie eine umgekehrte Version des Feldes speichern, wenn das Feld erstellt wird. Etwas wie das:

// 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);
}

Mit dieser Option können Sie die letzten Buchstaben eines Zeichenfolgenfelds und die ersten , nur nicht zufälligen Mittelbuchstaben oder Buchstabengruppen durchsuchen . Dies ist näher am gewünschten Ergebnis. Dies hilft uns jedoch nicht wirklich, wenn wir zufällige mittlere Buchstaben oder Wörter wollen. Denken Sie auch daran, alles in Kleinbuchstaben oder eine Kopie in Kleinbuchstaben für die Suche zu speichern, damit Groß- und Kleinschreibung kein Problem darstellt.

4.) Wenn Sie nur wenige Wörter haben, wird Ken Tans Methode alles tun, was Sie wollen, oder zumindest nachdem Sie sie leicht geändert haben. Mit nur einem Textabschnitt erstellen Sie jedoch exponentiell mehr als 1 MB Daten, was größer ist als die maximale Dokumentgröße des Firestores (ich weiß, ich habe es getestet).

5.) Wenn Sie Array- Enthaltene (oder irgendeine Form von Arrays) mit dem \uf8ffTrick kombinieren könnten, könnten Sie eine brauchbare Suche haben, die die Grenzen nicht erreicht. Ich habe jede Kombination ausprobiert, auch mit Karten, und ein No Go. Jeder, der das herausfindet, poste es hier.

6.) Wenn Sie sich von ALGOLIA und ELASTIC SEARCH entfernen müssen und ich Ihnen überhaupt keine Vorwürfe mache, können Sie jederzeit mySQL, postSQL oder neo4Js in Google Cloud verwenden. Sie sind alle 3 einfach einzurichten und haben freie Ebenen. Sie hätten eine Cloud-Funktion zum Speichern der Daten onCreate () und eine andere onCall () -Funktion zum Durchsuchen der Daten. Einfach ... ish. Warum nicht einfach zu mySQL wechseln? Die Echtzeitdaten natürlich! Wenn jemand DGraph mit Websocken für Echtzeitdaten schreibt , zählen Sie mich mit!

Algolia und ElasticSearch wurden als reine Suchdatenbanken entwickelt, daher gibt es nichts so schnelles ... aber Sie zahlen dafür. Google, warum führen Sie uns von Google weg und folgen Sie MongoDB noSQL nicht und erlauben Sie Suchvorgänge?

UPDATE - ICH HABE EINE LÖSUNG ERSTELLT:

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

Jonathan
quelle
Ein toller Überblick und sehr hilfreich.
RedFilter
Genial! Upvote für eine gut strukturierte und informative Antwort.
König des Dschungels
Es ist großartig, danke
Giang
10

Späte Antwort, aber für alle, die noch nach einer Antwort suchen: Nehmen wir an, wir haben eine Sammlung von Benutzern und in jedem Dokument der Sammlung ein Feld "Benutzername". Wenn Sie also ein Dokument suchen möchten, in dem der Benutzername mit "al" beginnt, wir können so etwas tun

 FirebaseFirestore.getInstance().collection("users").whereGreaterThanOrEqualTo("username", "al")
MoTahir
quelle
Dies ist eine großartige und einfache Lösung. Danke. Was aber, wenn Sie mehr als ein Feld überprüfen möchten? Wie "Name" und "Beschreibung" durch einen OP verbunden?
Versuchen Sie es am
Ich glaube nicht, dass Sie Abfragen basierend auf zwei Feldern durchführen können. Leider ist Firebase schlecht, wenn es um Abfragen geht. Sie können diese Hoffnung überprüfen. Es hilft stackoverflow.com/questions/26700924/…
MoTahir
1
Bestätigt, @MoTahir. Es gibt kein "ODER" im Firestore.
Rap
Diese
Bei der Abfrage nach ODER müssen lediglich zwei Suchergebnisse kombiniert werden. Das Sortieren dieser Ergebnisse ist ein anderes Problem ...
Jonathan
7

Ich bin mir sicher, dass Firebase bald "string-enthält" herausbringen wird, um jeden Index [i] startAt in der Zeichenfolge zu erfassen ... Aber ich habe die Websites recherchiert und festgestellt, dass diese Lösung von jemand anderem gedacht wurde, der Ihre Daten wie eingerichtet hat Dies

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
})

Geben Sie hier die Bildbeschreibung ein

Abfrage wie folgt

firebase
.firestore()
.collection("clubs")
.where(
 "titleAsArray",
 "array-contains",
 this.state.userQuery.toLowerCase()
)
Nick Carducci
quelle
Überhaupt nicht zu empfehlen. Da Dokumente ein Limit von 20.000 Zeilen haben, können Sie es einfach nicht auf diese Weise verwenden, bis Sie sicher sind, dass Ihr Dokument niemals solche Limits erreicht
Sandeep,
Es ist im Moment die beste Option. Was wird sonst noch empfohlen?
Nick Carducci
1
@Sandeep Ich bin mir ziemlich sicher, dass die Größe auf 1 MB Größe und 20 Tiefenstufen pro Dokument begrenzt ist. Was meinst du mit 20.000 Zeilen? Dies ist derzeit die beste Problemumgehung, wenn die Verwendung von Algolia oder ElasticSearch nicht in der Tabelle enthalten ist
ppicom
5

Wenn Sie keinen Drittanbieter-Service wie Algolia verwenden möchten, sind Firebase Cloud-Funktionen eine großartige Alternative. Sie können eine Funktion erstellen, die einen Eingabeparameter empfangen, serverseitig durch die Datensätze verarbeiten und dann diejenigen zurückgeben kann, die Ihren Kriterien entsprechen.

Rap
quelle
1
Was ist mit Android?
Pratik Butani
Schlagen Sie vor, dass Personen jeden einzelnen Datensatz in einer Sammlung durchlaufen?
DarkNeuron
Nicht wirklich. Ich würde Array.prototype verwenden. * - Wie .every (), .some (), .map (), .filter () usw. Dies erfolgt in Node auf dem Server in einer Firebase-Funktion, bevor Werte an die zurückgegeben werden Klient.
Rap
3
Sie müssten immer noch ALLE Dokumente lesen, um sie zu durchsuchen, was Kosten verursacht und zeitaufwändig ist.
Jonathan
3

Ich denke tatsächlich, dass die beste Lösung, um dies in Firestore zu tun, darin besteht, alle Teilzeichenfolgen in ein Array einzufügen und einfach eine Abfrage array_contains durchzuführen. Auf diese Weise können Sie Teilzeichenfolgenabgleiche durchführen. Ein bisschen übertrieben, um alle Teilzeichenfolgen zu speichern, aber wenn Ihre Suchbegriffe kurz sind, ist es sehr, sehr vernünftig.

Dan Fein
quelle
2

Ich hatte gerade dieses Problem und fand eine ziemlich einfache Lösung.

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

Mit isGreaterThanOrEqualTo können wir den Beginn unserer Suche herausfiltern. Durch Hinzufügen eines "z" am Ende von isLessThanOrEqualTo können wir unsere Suche so begrenzen, dass nicht mit den nächsten Dokumenten fortgefahren wird.

Jacob Bonk
quelle
3
Ich habe diese Lösung ausprobiert, aber für mich funktioniert sie nur, wenn die vollständige Zeichenfolge eingegeben wird. Wenn ich zum Beispiel den Begriff "frei" erhalten möchte, wenn ich anfange, "fr" einzugeben, wird nichts zurückgegeben. Sobald ich "frei" eingebe, gibt mir der Begriff seinen Schnappschuss.
Chris
Verwenden Sie das gleiche Codeformat? Und ist der Begriff eine Zeichenfolge im Firestore? Ich weiß, dass Sie nicht nach der documentId filtern können.
Jacob Bonk
2

Die ausgewählte Antwort funktioniert nur für exakte Suchvorgänge und ist kein natürliches Suchverhalten der Benutzer (die Suche nach "Apfel" in "Joe hat heute einen Apfel gegessen" würde nicht funktionieren).

Ich denke, Dan Feins Antwort oben sollte höher eingestuft werden. Wenn die von Ihnen durchsuchten Zeichenfolgendaten kurz sind, können Sie alle Teilzeichenfolgen der Zeichenfolge in einem Array in Ihrem Dokument speichern und dann mit der Abfrage array_contains von Firebase das Array durchsuchen. Firebase-Dokumente sind auf 1 MiB (1.048.576 Byte) ( Firebase-Kontingente und -Limits ) begrenzt, was ungefähr 1 Million Zeichen entspricht, die in einem Dokument gespeichert sind (ich denke 1 Zeichen ~ = 1 Byte). Das Speichern der Teilzeichenfolgen ist in Ordnung, solange Ihr Dokument nicht nahe an der 1-Millionen-Marke liegt.

Beispiel für die Suche nach Benutzernamen:

Schritt 1: Fügen Sie Ihrem Projekt die folgende String-Erweiterung hinzu. Auf diese Weise können Sie einen String einfach in Teilzeichenfolgen aufteilen. ( Ich habe das hier gefunden ).

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])
}

Schritt 2: Wenn Sie den Namen eines Benutzers speichern, speichern Sie auch das Ergebnis dieser Funktion als Array im selben Dokument. Dadurch werden alle Variationen des Originaltextes erstellt und in einem Array gespeichert. Beispielsweise würde die Texteingabe "Apple" das folgende Array erstellen: ["a", "p", "p", "l", "e", "ap", "pp", "pl", "le" "," app "," ppl "," ple "," appl "," pple "," apple "], die alle Suchkriterien umfassen sollten, die ein Benutzer eingeben könnte. Sie können MaximumStringSize als Null belassen, wenn Sie alle Ergebnisse erzielen möchten. Wenn jedoch langer Text vorhanden ist, würde ich empfehlen, ihn zu begrenzen, bevor die Dokumentgröße zu groß wird - ungefähr 15 funktionieren für mich gut (die meisten Leute suchen sowieso nicht nach langen Phrasen ).

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
}

Schritt 3: Sie können die Funktion array_contains von Firebase verwenden!

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

Mit Firestore können Sie eine Volltextsuche implementieren, die jedoch immer noch mehr Lesevorgänge kostet als sonst. Außerdem müssen Sie die Daten auf eine bestimmte Weise eingeben und indizieren. Bei diesem Ansatz können Sie also Firebase-Cloud-Funktionen verwenden Tokenisieren und hashen Sie dann Ihren Eingabetext, während Sie eine lineare Hash-Funktion auswählen h(x), die die folgenden Anforderungen erfüllt - if x < y < z then h(x) < h (y) < h(z). Für die Tokenisierung können Sie einige leichtgewichtige NLP-Bibliotheken auswählen, um die Kaltstartzeit Ihrer Funktion niedrig zu halten und unnötige Wörter aus Ihrem Satz zu entfernen. Anschließend können Sie im Firestore eine Abfrage mit einem Operator kleiner und größer als ausführen. Während Sie Ihre Daten auch speichern, müssen Sie sicherstellen, dass Sie den Text hashen, bevor Sie ihn speichern, und den Nur-Text so speichern, als ob Sie den Nur-Text ändern, ändert sich auch der Hash-Wert.

Adarsh ​​Srivastava
quelle
0

Dies hat bei mir perfekt funktioniert, kann aber zu Leistungsproblemen führen.

Tun Sie dies, wenn Sie den Firestore abfragen:

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

Tun Sie dies in Ihrem 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);
            })
   };
Arun Yogeshwaran
quelle
-10

Mit dem Back-Tick können wir den Wert einer Zeichenfolge ausdrucken. Das sollte funktionieren:

where('name', '==', `${searchTerm}`)
Zach J.
quelle
Danke, aber bei dieser Frage geht es darum, ungenaue Werte zu erhalten. Das fragliche Beispiel funktioniert beispielsweise, wenn der Name genau ist. Wenn ich ein Dokument mit dem Namen "Test" habe und dann nach "Test" suche, funktioniert es. Aber ich würde erwarten, nach "tes" oder "est" suchen zu können und trotzdem das "Test" -Ergebnis zu erhalten. Stellen Sie sich einen Anwendungsfall mit Buchtiteln vor. Menschen suchen oft eher nach Teilbuchtiteln als nach dem genauen Titel.
ausfallsichere
12
@suulisin du hast recht, ich habe es nicht sorgfältig gelesen, da ich zu eifrig war zu teilen, was ich gefunden hatte. Vielen Dank für Ihre Bemühungen, darauf hinzuweisen, und ich werde vorsichtiger sein
Zach J