Google App Engine: est-il possible de faire une requête Gql LIKE?


123

Simple vraiment. En SQL, si je veux rechercher un champ de texte pour quelques caractères, je peux faire:

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

La documentation d'App Engine ne mentionne pas comment y parvenir, mais c'est sûrement un problème assez courant?


3
Le problème persistant tourne autour des personnes qui essaient d'utiliser GAE Datastore comme s'il s'agissait d'une base de données Relational / ~ SQL. En introduisant GQL, Google amène davantage les gens à penser en termes de systèmes SQL. Cependant, je comprends que Google essaie de rendre la transition pour tout le monde beaucoup plus facile même si je ne suis pas sûr que ce soit la bonne approche.
fuentesjr

Réponses:


81

BigTable, qui est le backend de la base de données pour App Engine, évoluera jusqu'à des millions d'enregistrements. Pour cette raison, App Engine ne vous autorisera pas à effectuer des requêtes qui entraîneront une analyse de table, car les performances seraient terribles pour une table bien remplie.

En d'autres termes, chaque requête doit utiliser un index. C'est pourquoi vous ne pouvez le faire =, >et les <requêtes. (En fait, vous pouvez également le faire, !=mais l'API le fait en utilisant une combinaison de >et de <requêtes.) C'est également pourquoi l'environnement de développement surveille toutes les requêtes que vous faites et ajoute automatiquement les index manquants à votre index.yamlfichier.

Il n'y a aucun moyen d'indexer une LIKErequête, elle n'est donc tout simplement pas disponible.

Regardez cette session Google IO pour une explication bien meilleure et plus détaillée à ce sujet.


77

Je suis confronté au même problème, mais j'ai trouvé quelque chose sur les pages du moteur d'application Google:

Conseil: Les filtres de requête n'ont pas de moyen explicite de faire correspondre uniquement une partie d'une valeur de chaîne, mais vous pouvez simuler une correspondance de préfixe à l'aide de filtres d'inégalité:

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

Cela correspond à chaque entité MyModel avec une propriété de chaîne prop qui commence par les caractères abc. La chaîne Unicode u "\ ufffd" représente le plus grand caractère Unicode possible. Lorsque les valeurs de propriété sont triées dans un index, les valeurs comprises dans cette plage sont toutes les valeurs commençant par le préfixe donné.

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

peut-être que cela pourrait faire l'affaire;)


6
+1 Il vaut la peine de souligner que c'est sensible à la casse. Heureusement, les données du champ que j'interroge sont converties en minuscules avant d'être stockées.
Cuga

12

Si App Engine ne prend pas en charge les requêtes LIKE, jetez un œil aux propriétés ListProperty et StringListProperty . Lorsqu'un test d'égalité est effectué sur ces propriétés, le test sera effectivement appliqué à tous les membres de la liste, par exemple, il list_property = valueteste si la valeur apparaît n'importe où dans la liste.

Parfois, cette fonctionnalité peut être utilisée comme solution de contournement au manque de requêtes LIKE. Par exemple, il permet de faire une recherche de texte simple, comme décrit dans cet article .


3
le message n'existe plus
mwm

9

Vous devez utiliser le service de recherche pour effectuer des requêtes de recherche en texte intégral similaires à SQL LIKE.

Gaelyk fournit un langage spécifique au domaine pour effectuer des requêtes de recherche plus conviviales . Par exemple, l'extrait de code suivant trouvera les dix premiers livres triés à partir des derniers avec le titre contenant fern et le genre correspondant exactement 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 est écrit comme l'opérateur de correspondance de Groovy =~. Il prend également en charge des fonctions telles que distance(geopoint(lat, lon), location).



3

Jetez un œil à Objectify ici , c'est comme une API d'accès au magasin de données. Il y a une FAQ avec cette question spécifiquement, voici la réponse

Comment faire une requête similaire (LIKE "foo%")
Vous pouvez faire quelque chose comme un startWith, ou endWith si vous inversez l'ordre lors du stockage et de la recherche. Vous effectuez une requête de plage avec la valeur de départ souhaitée et une valeur juste au-dessus de celle que vous souhaitez.

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

1
il recherchera "commence par" et non "Contient".
Hardik Patel

1

Suivez simplement ici: init.py # 354 "> http://code.google.com/p/googleappengine/source/browse/trunk/python/google/appengine/ext/search/ init .py # 354

Ça marche!

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

J'ai testé cela avec l'API Java de bas niveau GAE Datastore. Moi et fonctionne parfaitement

    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
cela fonctionne pour le préfixe, mais que faire si je veux faire correspondre à partir de la fin de la chaîne? Par exemple - je veux rechercher abc dans sdfdsabc, alors il devrait renvoyer sdfdsabc
user1930106

1

En général, même s'il s'agit d'un ancien article, un moyen de produire un 'LIKE' ou 'ILIKE' est de rassembler tous les résultats d'une requête '> =', puis de boucler les résultats en python (ou Java) pour les éléments contenant ce que vous cherchez.

Supposons que vous souhaitiez filtrer les utilisateurs avec aq = 'luigi'

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

Il n'est pas possible de faire une recherche LIKE sur le moteur d'application du magasin de données, mais la création d'un Arraylist ferait l'affaire si vous avez besoin de rechercher un mot dans une chaîne.

@Index
    public ArrayList<String> searchName;

puis pour rechercher dans l'index en utilisant objectify.

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

et cela vous donnera une liste de tous les éléments qui contiennent le monde que vous avez fait lors de la recherche


0

Si le se LIKE '%text%'compare toujours à un mot ou à quelques-uns (pensez aux permutations) et que vos données changent lentement (cela signifie lentement qu'il n'est pas prohibitif - à la fois en termes de prix et de performances - de créer et de mettre à jour des index), alors Relation Index Entity (RIE) peut être la réponse.

Oui, vous devrez créer une entité de banque de données supplémentaire et la remplir de manière appropriée. Oui, vous devrez jouer avec certaines contraintes (l'une est la limite de 5000 sur la longueur de la propriété de liste dans la banque de données GAE). Mais les recherches qui en résultent sont rapides comme l'éclair.

Pour plus de détails, consultez mon RIE avec Java et Ojbectify et RIE avec des publications Python .


0

"J'aime" est souvent utilisé comme un substitut du pauvre à la recherche de texte. Pour la recherche de texte, il est possible d'utiliser Whoosh-AppEngine .

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.