Google App Engine: Ist es möglich, eine Gql LIKE-Abfrage durchzuführen?


123

Wirklich einfach. Wenn ich in SQL ein Textfeld nach mehreren Zeichen durchsuchen möchte, kann ich Folgendes tun:

SELECT blah FROM blah WHERE blah LIKE '%text%'

In der Dokumentation zu App Engine wird nicht erwähnt, wie dies erreicht werden kann, aber es ist sicherlich ein häufig genug auftretendes Problem.


3
Das anhaltende Problem dreht sich um Personen, die versuchen, GAE Datastore so zu verwenden, als wäre es eine relationale / ~ SQL-Datenbank. Durch die Einführung von GQL durch Google werden die Menschen dazu gebracht, in SQL-Systemen zu denken. Ich verstehe jedoch, dass Google versucht, den Übergang für alle viel einfacher zu gestalten, obwohl ich nicht sicher bin, ob dies der richtige Ansatz ist.
Fuentesjr

Antworten:


81

BigTable, das Datenbank-Backend für App Engine, wird auf Millionen von Datensätzen skaliert. Aus diesem Grund können Sie mit App Engine keine Abfragen durchführen, die zu einem Tabellenscan führen, da die Leistung für eine gut bestückte Tabelle schrecklich wäre.

Mit anderen Worten, jede Abfrage muss einen Index verwenden. Aus diesem Grund können Sie nur tun =, >und <Abfragen. (Tatsächlich können Sie dies auch tun, !=aber die API tut dies mit einer Kombination aus >und< Abfragen durch.) Aus diesem Grund überwacht die Entwicklungsumgebung alle von Ihnen ausgeführten Abfragen und fügt Ihren fehlenden Indizes automatisch alle fehlenden Indizes hinzuindex.yaml Datei .

Es gibt keine Möglichkeit, für a zu indizieren LIKE Abfrage daher ist sie einfach nicht verfügbar.

Sehen Sie sich diese Google IO-Sitzung an, um eine viel bessere und detailliertere Erklärung zu erhalten.


77

Ich habe das gleiche Problem, aber ich habe etwas auf den Seiten der Google App Engine gefunden:

Tipp: Abfragefilter haben keine explizite Möglichkeit, nur einen Teil eines Zeichenfolgenwerts abzugleichen. Sie können jedoch eine Präfixübereinstimmung mithilfe von Ungleichheitsfiltern vortäuschen:

db.GqlQuery("SELECT * FROM MyModel WHERE prop >= :1 AND prop < :2",
            "abc",
            u"abc" + u"\ufffd")

Dies ordnet jeder MyModel-Entität eine Zeichenfolge-Eigenschaft zu, die mit den Zeichen abc beginnt. Die Unicode-Zeichenfolge u "\ ufffd" repräsentiert das größtmögliche Unicode-Zeichen. Wenn die Eigenschaftswerte in einem Index sortiert sind, sind die Werte, die in diesen Bereich fallen, alle Werte, die mit dem angegebenen Präfix beginnen.

http://code.google.com/appengine/docs/python/datastore/queriesandindexes.html

vielleicht könnte das den Trick machen;)


6
+1 Es ist jedoch darauf hinzuweisen, dass zwischen Groß- und Kleinschreibung unterschieden wird. Glücklicherweise werden die Daten in dem Feld, das ich abfrage, vor dem Speichern in Kleinbuchstaben umgewandelt.
Cuga

12

Obwohl App Engine keine LIKE-Abfragen unterstützt, sehen Sie sich die Eigenschaften ListProperty und StringListProperty an . Wenn ein Gleichheitstest für diese Eigenschaften durchgeführt wird, wird der Test tatsächlich auf alle Listenmitglieder angewendet, z.list_property = value Tests, ob der Wert an einer beliebigen Stelle in der Liste angezeigt wird.

Manchmal kann diese Funktion als Problemumgehung für das Fehlen von LIKE-Abfragen verwendet werden. Zum Beispiel ermöglicht es die einfache Textsuche, wie in diesem Beitrag beschrieben .


3
Der Beitrag existiert nicht mehr
mwm

9

Sie müssen den Suchdienst verwenden , um Volltextsuchabfragen ähnlich wie bei SQL durchzuführen LIKE.

Gaelyk bietet eine domänenspezifische Sprache, um benutzerfreundlichere Suchanfragen durchzuführen . Im folgenden Snippet finden Sie beispielsweise die ersten zehn Bücher, die nach den neuesten Büchern sortiert sind, deren Titel fern und das Genre genau übereinstimmen thriller:

def documents = search.search {
    select all from books
    sort desc by published, SearchApiLimits.MINIMUM_DATE_VALUE
    where title =~ 'fern'
    and genre =  'thriller'
    limit 10
}

Like ist als Groovys Match-Operator geschrieben =~. Es unterstützt auch Funktionen wie distance(geopoint(lat, lon), location).



3

Schauen Sie sich Objectify hier an , es ist wie eine Datenspeicher-Zugriffs-API. Es gibt eine FAQ mit dieser Frage speziell, hier ist die Antwort

Wie mache ich eine ähnliche Abfrage (LIKE "foo%")
? Sie können so etwas wie startWith oder endWith ausführen, wenn Sie die Reihenfolge beim Speichern und Durchsuchen umkehren. Sie führen eine Bereichsabfrage mit dem gewünschten Startwert und einem Wert direkt über dem gewünschten Wert durch.

String start = "foo";
    ... = ofy.query(MyEntity.class).filter("field >=", start).filter("field <", start + "\uFFFD");

1
es wird gesucht "beginnt mit" nicht "enthält".
Hardik Patel

1

Folgen Sie einfach hier: init.py # 354 "> http://code.google.com/p/googleappengine/source/browse/trunk/python/google/appengine/ext/search/ init .py # 354

Es klappt!

class Article(search.SearchableModel):
    text = db.TextProperty()
    ...

  article = Article(text=...)
  article.save()

To search the full text index, use the SearchableModel.all() method to get an
instance of SearchableModel.Query, which subclasses db.Query. Use its search()
method to provide a search query, in addition to any other filters or sort
orders, e.g.:

  query = article.all().search('a search query').filter(...).order(...)

1

Ich habe dies mit der Java-API von GAE Datastore auf niedriger Ebene getestet. Ich und funktioniert perfekt

    Query q = new Query(Directorio.class.getSimpleName());

    Filter filterNombreGreater = new FilterPredicate("nombre", FilterOperator.GREATER_THAN_OR_EQUAL, query);
    Filter filterNombreLess = new FilterPredicate("nombre", FilterOperator.LESS_THAN, query+"\uFFFD");
    Filter filterNombre =  CompositeFilterOperator.and(filterNombreGreater, filterNombreLess);

    q.setFilter(filter);

1
Dies funktioniert für das Präfix, aber was ist, wenn ich vom Ende der Zeichenfolge aus übereinstimmen möchte? Zum Beispiel - ich möchte abc in sdfdsabc suchen, dann sollte es sdfdsabc zurückgeben
user1930106

1

Obwohl dies ein alter Beitrag ist, besteht eine Möglichkeit, ein 'LIKE' oder 'ILIKE' zu erstellen, darin, alle Ergebnisse aus einer '> =' - Abfrage zu sammeln und dann die Ergebnisse in Python (oder Java) für Elemente zu schleifen, die das enthalten, was Sie enthalten suchen.

Angenommen, Sie möchten Benutzer mit aq = 'luigi' filtern.

users = []
qry = self.user_model.query(ndb.OR(self.user_model.name >= q.lower(),self.user_model.email >= q.lower(),self.user_model.username >= q.lower()))

for _qry in qry:
 if q.lower() in _qry.name.lower() or q.lower() in _qry.email.lower() or q.lower() in _qry.username.lower():
      users.append(_qry)

1

Es ist nicht möglich, eine LIKE-Suche in der Datenspeicher-App-Engine durchzuführen. Wie auch immer, das Erstellen einer Arrayliste würde den Trick tun, wenn Sie ein Wort in einer Zeichenfolge suchen müssen.

@Index
    public ArrayList<String> searchName;

und dann mit objectify im Index zu suchen.

List<Profiles> list1 = ofy().load().type(Profiles.class).filter("searchName =",search).list();

Auf diese Weise erhalten Sie eine Liste mit allen Elementen, die die Welt enthalten, die Sie bei der Suche erstellt haben


0

Wenn das LIKE '%text%'immer mit einem Wort oder ein paar verglichen wird (denken Sie an Permutationen) und sich Ihre Daten langsam ändern (langsam bedeutet dies, dass das Erstellen und Aktualisieren von Indizes sowohl preislich als auch leistungsmäßig nicht unerschwinglich teuer ist), dann Relation Index Entity (RIE) kann die Antwort sein.

Ja, Sie müssen eine zusätzliche Datenspeicherentität erstellen und diese entsprechend füllen. Ja, es gibt einige Einschränkungen, die Sie umgehen müssen (eine ist die Beschränkung der Länge der Listeneigenschaft im GAE-Datenspeicher auf 5000). Die daraus resultierenden Suchanfragen sind jedoch blitzschnell.

Für Details siehe meine RIE mit Java und Ojbectify und RIE mit Python- Posts.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.