Google App Engine: ¿es posible hacer una consulta Gql LIKE?


123

Simple de verdad. En SQL, si quiero buscar en un campo de texto un par de caracteres, puedo hacer:

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

La documentación de App Engine no menciona cómo lograr esto, pero ¿seguramente es un problema bastante común?


3
El problema continuo gira en torno a las personas que intentan usar el almacén de datos GAE como si fuera una base de datos relacional / ~ SQL. Al introducir Google GQL, lleva a las personas a pensar en términos de sistemas SQL. Sin embargo, entiendo que Google está tratando de hacer la transición para todos mucho más fácil, aunque no estoy seguro de que este sea el enfoque correcto.
fuentesjr

Respuestas:


81

BigTable, que es el back-end de la base de datos para App Engine, escalará a millones de registros. Debido a esto, App Engine no le permitirá realizar ninguna consulta que resulte en un escaneo de tabla, ya que el rendimiento sería terrible para una tabla bien poblada.

En otras palabras, cada consulta debe usar un índice. Es por eso que solo puede hacer =, >y <consultas. (De hecho, también puede hacerlo, !=pero la API lo hace utilizando una combinación de >y <consultas). Esta es también la razón por la cual el entorno de desarrollo supervisa todas las consultas que realiza y agrega automáticamente los índices faltantes a su index.yamlarchivo.

No hay forma de indexar una LIKEconsulta, por lo que simplemente no está disponible.

Observe esta sesión de Google IO para obtener una explicación mucho mejor y más detallada de esto.


77

Estoy enfrentando el mismo problema, pero encontré algo en las páginas del motor de aplicaciones de Google:

Consejo: Los filtros de consulta no tienen una forma explícita de hacer coincidir solo parte de un valor de cadena, pero puede simular una coincidencia de prefijo utilizando filtros de desigualdad:

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

Esto hace coincidir cada entidad MyModel con una propiedad de cadena que comienza con los caracteres abc. La cadena unicode u "\ ufffd" representa el carácter Unicode más grande posible. Cuando los valores de propiedad se ordenan en un índice, los valores que se encuentran en este rango son todos los valores que comienzan con el prefijo dado.

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

tal vez esto podría hacer el truco;)


66
+1 Aunque vale la pena señalar que esto distingue entre mayúsculas y minúsculas. Afortunadamente, los datos en el campo que estoy consultando se convierten en minúsculas antes de almacenarlos.
Cuga

12

Aunque App Engine no admite consultas LIKE, eche un vistazo a las propiedades ListProperty y StringListProperty . Cuando se realiza una prueba de igualdad en estas propiedades, la prueba se aplicará realmente a todos los miembros de la lista, por ejemplo, list_property = valueprueba si el valor aparece en algún lugar de la lista.

A veces, esta característica puede usarse como una solución alternativa a la falta de consultas LIKE. Por ejemplo, hace posible realizar una búsqueda de texto simple, como se describe en esta publicación .


3
la publicación ya no existe
mwm

9

Debe usar el servicio de búsqueda para realizar consultas de búsqueda de texto completo similares a SQL LIKE.

Gaelyk proporciona un lenguaje específico de dominio para realizar consultas de búsqueda más fáciles de usar . Por ejemplo, el siguiente fragmento encontrará los primeros diez libros ordenados de los últimos con el título que contiene fern y el género que coincide exactamente 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á escrito como el operador de partido de Groovy =~. Es compatible con funciones distance(geopoint(lat, lon), location)como también.



3

Eche un vistazo a Objectify aquí , es como una API de acceso al almacén de datos. Hay una pregunta frecuente con esta pregunta específicamente, aquí está la respuesta

¿Cómo hago una consulta similar (LIKE "foo%")
? Puede hacer algo como startWith o endWith si invierte el orden cuando se almacena y se busca. Realiza una consulta de rango con el valor inicial que desea y un valor justo por encima del que desea.

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

1
buscará "comienza con" no "Contiene".
Hardik Patel el

1

Simplemente siga aquí: init.py # 354 "> http://code.google.com/p/googleappengine/source/browse/trunk/python/google/appengine/ext/search/ init .py # 354

¡Funciona!

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

Probé esto con la API Java de bajo nivel GAE Datastore. Yo y funciona perfectamente

    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
esto funciona para el prefijo, pero ¿qué pasa si quiero coincidir desde el final de la cadena? Por ejemplo, quiero buscar abc en sdfdsabc, entonces debería devolver sdfdsabc
user1930106

1

En general, a pesar de que esta es una publicación antigua, una forma de producir un 'LIKE' o 'ILIKE' es reunir todos los resultados de una consulta '> =', luego hacer un bucle en Python (o Java) para los elementos que contienen lo que 'que estas buscando.

Digamos que desea filtrar usuarios dados 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

No es posible hacer una búsqueda ME GUSTA en el motor de la aplicación del almacén de datos, sin embargo, crear una Arraylist sería suficiente si necesita buscar una palabra en una cadena.

@Index
    public ArrayList<String> searchName;

y luego buscar en el índice usando objectify.

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

y esto te dará una lista con todos los elementos que contienen el mundo que hiciste en la búsqueda


0

Si LIKE '%text%'siempre se compara con una palabra o unas pocas (piense en permutaciones) y sus datos cambian lentamente (lentamente significa que no es prohibitivamente costoso, tanto en términos de precio como de rendimiento, crear y actualizar índices), entonces Entidad de índice de relación (RIE) puede ser la respuesta

Sí, tendrá que crear una entidad de almacenamiento de datos adicional y completarla de manera adecuada. Sí, hay algunas restricciones con las que tendrá que jugar (una es el límite de 5000 en la longitud de la propiedad de lista en el almacén de datos GAE). Pero las búsquedas resultantes son muy rápidas.

Para más detalles, vea mi RIE con Java y Ojbectify y RIE con publicaciones de Python .


0

"Me gusta" se usa a menudo como sustituto de un pobre para la búsqueda de texto. Para la búsqueda de texto, es posible usar Whoosh-AppEngine .

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.