Échapper aux requêtes de recherche pour le service de recherche en texte intégral de Google

This is a cross-post of https://groups.google.com/d/topic/google-appengine/97LY3Yfd_14/discussion

Je travaille avec le nouveau service de recherche de texte intégral dans gae 1.6.6 et je n'arrive pas à trouver comment échapper correctement mes chaînes de requête avant de les transmettre à l'index de recherche. Les docs mentionnent que certains caractères doivent être échappés (à savoir les opérateurs numériques ), cependant ils ne spécifient pas comment l'analyseur de requête s'attend à ce que la chaîne soit échappée.

Le problème que je rencontre est double:

  1. Failing to escape the crap out of many characters (more than those that are hinted at in the docs) will cause the parser to raise a QueryException.
  2. When I've escaped the query to the point it won't raise, the numeric operators (>, <, >=, <=) no longer parse correctly (not factored into the search).

Je configure un test où je place string.printable dans my_index.search() et trouve qu'il soulèverait QueryException sur chacun des "printable "les caractères de contrôle, que je suis en train de retirer, ainsi que des choses qui sembleraient innocentes comme un astérisque, une virgule, des parenthèses, des accolades, un tilde. Aucun de ceux-ci n'est mentionné dans les documents comme devant être échappé.

Jusqu'ici j'ai essayé:

  • cgi.escape()
  • saxutils.escape() with a mapping of ascii to urlencoded equivalents (eg , -> %2C)
  • saxutils.escape() with a mapping of ascii to html entity encoded ascii codes (eg {)
  • urllib.quote_plus()

I've gotten the best results so far using url-style(%NN) replacements, but >, <, >=, and <= continue to fail to yield the expected results from the index. Also, and this doesn't really seem to have anything to do with the escaping issue, but using NOT in front of a field = value type query seems to not be working as advertised either.

tl; dr

Comment devrais-je échapper mes requêtes avant de les envoyer au service de recherche afin que l'analyseur ne lève pas QueryException et ma requête donne les résultats attendus?

0

1 Réponses

comme expliqué brièvement dans la documentation ( https://developers.google.com/ appengine/docs/python/recherche/vue d'ensemble # Query_Language_Overview ), le paramètre query est une chaîne qui doit correspondre à notre langage de requête. Ce que nous devrions mieux documenter.

Pour l'instant, je vous recommande d'envelopper vos requêtes (ou au moins certains des mots/termes) entre guillemets. De cette façon, vous seriez en mesure de passer tous les caractères imprimables, mais "et." L'exemple suivant montre le résultat.

import string
from google.appengine.api.search import Query
Query('"%s"' % string.printable.replace('"', '').replace('\\', ''))

et vous pouvez même passer des caractères non imprimables

Query('"%s"' % ''.join(chr(i) for i in xrange(128)).replace('"','').replace('\\', ''))

EDIT: Note that anything that is enclosed in double quotes is an exact match, that is "foo bar" would match against ...foo bar... but no ...bar foo..

0
ajouté
Serait-il possible de donner un exemple plus pratique? Étant donné une requête de quelque chose comme created> = 2009-20-13 ET description: foobar , comment feriez-vous pour échapper à cela?
ajouté l'auteur Owen Nelson, source
Ok, je commence à voir. C'est en effet contextuel (comme je l'ai fait allusion dans mes groupes post). foo> = 123 fonctionne sans intervention, mais foo> = 123> déclenchera une exception. Il semble que j'ai besoin de construire un parseur pré-analyseur afin de gérer cela complètement. C'est gênant.
ajouté l'auteur Owen Nelson, source
De plus, le champ supérieur à, inférieur à celui de ma date semble ne pas fonctionner du tout, même si vous fournissez une requête civile bien formée.
ajouté l'auteur Owen Nelson, source
Je vois en quelque sorte où vous allez avec cette question. Je regarde maintenant 2 contextes différents pour exécuter des requêtes: le 1er est quand je prépare la requête pour l'utilisateur (sûr, n'a pas besoin d'être échappé) et le 2ème étant des requêtes venant de l'utilisateur (que je devrais être arrachement brutal des barbes et des épines quand il entre).
ajouté l'auteur Owen Nelson, source
Cette réponse modifie le terme de recherche d'origine en supprimant les guillemets qui pourraient faire partie de la requête. Au lieu de cela, j'utilise le remplacement suivant avec succès, qui échappe simplement aux guillemets dans le terme de recherche: search_term.replace ('"', '\\"')
ajouté l'auteur Nick Franceschina, source
La requête que vous avez fournie n'a pas besoin d'être échappée Query ('created> = 2009-20-13 AND description: foobar') fonctionne correctement. Si vous recherchez réellement la chaîne 'created> = 2009-20-13 AND description: foobar' dans vos documents, vous devez placer la chaîne entre guillemets. Mais en règle générale, je placerais entre guillemets tout opérateur défini dans la documentation si je veux les utiliser en tant que caractères et non en tant qu'opérateurs.
ajouté l'auteur Sebastian Kreft, source
Je suppose que vous recevez la chaîne de requête d'un utilisateur final. Droite?
ajouté l'auteur Sebastian Kreft, source
Cette réponse date de 2012 et mentionne "pour l'instant". Y a-t-il une meilleure façon de le faire maintenant? l'emballage entre guillemets n'est pas une solution souhaitable puisqu'il cherchera la chaîne exacte
ajouté l'auteur manubot, source