Google App Engine: é possível fazer uma consulta Gql LIKE?


123

Simples mesmo. No SQL, se eu quiser pesquisar um campo de texto por alguns caracteres, eu posso fazer:

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

A documentação do App Engine não menciona como conseguir isso, mas certamente é um problema bastante comum?


3
O problema contínuo gira em torno de pessoas que tentam usar o GAE Datastore como se fosse um banco de dados Relacional / ~ SQL. Ao introduzir o GQL, o Google ainda leva as pessoas a pensar em termos de sistemas SQL. No entanto, eu entendo que o Google está tentando facilitar a transição para todos, mesmo não tendo certeza de que essa é a abordagem correta.
12409 fuentesjr

Respostas:


81

O BigTable, que é o back-end do banco de dados do App Engine, será escalado para milhões de registros. Devido a isso, o App Engine não permitirá que você faça nenhuma consulta que resultará em uma verificação de tabela, pois o desempenho seria terrível para uma tabela bem preenchida.

Em outras palavras, toda consulta deve usar um índice. É por isso que você só pode fazer =, >e <consultas. (Na verdade, você também pode fazer isso, !=mas a API faz isso usando uma combinação de >e <consultas.) É também por isso que o ambiente de desenvolvimento monitora todas as consultas que você faz e adiciona automaticamente quaisquer índices ausentes ao seuindex.yaml arquivo.

Não há como indexar uma LIKEconsulta, portanto ela simplesmente não está disponível.

Assista a esta sessão de IO do Google para obter uma explicação muito melhor e mais detalhada sobre isso.


77

Estou enfrentando o mesmo problema, mas encontrei algo nas páginas do Google App Engine:

Dica: Os filtros de consulta não têm uma maneira explícita de corresponder apenas a parte de um valor de sequência, mas você pode falsificar uma correspondência de prefixo usando os filtros de desigualdade:

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

Isso corresponde a todas as entidades MyModel com um prop de propriedade de sequência que começa com os caracteres abc. A string unicode u "\ ufffd" representa o maior caractere Unicode possível. Quando os valores da propriedade são classificados em um índice, os valores que se enquadram nesse intervalo são todos os valores que começam com o prefixo fornecido.

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

talvez isso possa funcionar;)


6
+1 Vale ressaltar que isso faz distinção entre maiúsculas e minúsculas. Felizmente, os dados no campo que estou consultando são convertidos em minúsculas antes de serem armazenados.
Cuga

12

O Altough App Engine não oferece suporte a consultas LIKE, consulte as propriedades ListProperty e StringListProperty . Quando um teste de igualdade é feito nessas propriedades, o teste será realmente aplicado a todos os membros da lista, por exemplo, list_property = valuetesta se o valor aparece em qualquer lugar da lista.

Às vezes, esse recurso pode ser usado como uma solução alternativa para a falta de consultas LIKE. Por exemplo, torna possível fazer uma pesquisa de texto simples, conforme descrito nesta publicação .


3
o post não existe mais
mwm

9

Você precisa usar o serviço de pesquisa para executar consultas de pesquisa de texto completo semelhantes ao SQL LIKE.

Gaelyk fornece um idioma específico do domínio para realizar consultas de pesquisa mais amigáveis . Por exemplo, o snippet a seguir encontrará os dez primeiros livros classificados dos mais recentes com o título fern e o gênero exatamente correspondentes 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 é escrito como operador de correspondência de Groovy =~ . Ele suporta funções distance(geopoint(lat, lon), location)como também.



3

Dê uma olhada no Objectify aqui , é como uma API de acesso ao armazenamento de dados. Há uma FAQ com esta pergunta especificamente, aqui está a resposta

Como faço uma consulta semelhante (LIKE "foo%")
Você pode fazer algo como um startWith ou endWith se você reverter a ordem quando armazenada e pesquisada. Você faz uma consulta de intervalo com o valor inicial desejado e um valor logo acima do desejado.

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

1
procurará "começa com" não "Contém".
Hardik Patel

1

Basta seguir aqui: 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

Testei isso com a API Java de baixo nível do GAE Datastore. Eu e funciona perfeitamente

    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
isso funciona como prefixo, mas e se eu quiser corresponder a partir do final da string? Por exemplo - eu quero procurar abc no sdfdsabc, então ele deve retornar sdfdsabc
user1930106

1

Em geral, mesmo que essa seja uma postagem antiga, uma maneira de produzir um 'LIKE' ou 'ILIKE' é reunir todos os resultados de uma consulta '> =' e, em seguida, gerar resultados em loop em python (ou Java) para elementos contendo o que você está procurando.

Digamos que você queira filtrar usuários com 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

Não é possível fazer uma pesquisa LIKE no mecanismo de aplicativos do armazenamento de dados, como a criação de uma lista de matriz faria o truque se você precisar pesquisar uma palavra em uma string.

@Index
    public ArrayList<String> searchName;

e depois procurar no índice usando o objectify.

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

e isso fornecerá uma lista com todos os itens que contêm o mundo que você fez na pesquisa


0

Se LIKE '%text%'sempre se comparar a uma palavra ou a algumas (permutações de pensamento) e seus dados mudarem lentamente (lentamente significa que não é proibitivamente caro - tanto em termos de preço quanto em termos de desempenho - criar e atualizar índices), a Entidade de Índice de Relação (RIE) pode ser a resposta.

Sim, você precisará criar uma entidade adicional do armazenamento de dados e preenchê-la adequadamente. Sim, existem algumas restrições que você precisará contornar (uma é o limite de 5000 no comprimento da propriedade da lista no armazenamento de dados GAE). Mas as pesquisas resultantes são extremamente rápidas.

Para obter detalhes, consulte minhas publicações RIE com Java e Ojbectify e RIE com Python .


0

"Gosto" é frequentemente usado como substituto de um pobre homem para a pesquisa de texto. Para pesquisa de texto, é possível usar o Whoosh-AppEngine .

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.