App Engine Datastore na operadora - como usar?
-
05-07-2019 - |
Pergunta
Reading: http://code.google.com/appengine /docs/python/datastore/gqlreference.html
Eu quero usar:
: = IN
mas estou inseguro sobre como fazê-lo funcionar. Vamos supor o seguinte
class User(db.Model):
name = db.StringProperty()
class UniqueListOfSavedItems(db.Model):
str = db.StringPropery()
datesaved = db.DateTimeProperty()
class UserListOfSavedItems(db.Model):
name = db.ReferenceProperty(User, collection='user')
str = db.ReferenceProperty(UniqueListOfSavedItems, collection='itemlist')
Como posso fazer uma consulta que me recebe a lista de itens salvos para um usuário? Obviamente, eu posso fazer:
q = db.Gql("SELECT * FROM UserListOfSavedItems WHERE name :=", user[0].name)
mas que me recebe uma lista de chaves. Quero agora tomar essa lista e colocá-lo em uma consulta para obter o campo str fora do UniqueListOfSavedItems. Eu pensei que eu poderia fazer:
q2 = db.Gql("SELECT * FROM UniqueListOfSavedItems WHERE := str in q")
mas algo não está certo ... alguma idéia? É (am em meu trabalho do dia, por isso não pode testar isso agora):
q2 = db.Gql("SELECT * FROM UniqueListOfSavedItems __key__ := str in q)
nota:. O que é um problema diabolicamente difícil de pesquisar sobre porque tudo que eu realmente se preocupam é o operador "IN"
Solução
Uma vez que você tem uma lista de chaves, você não precisa fazer uma segunda consulta - você pode fazer um lote buscar, em seu lugar. Tente isto:
#and this should get me the items that a user saved
useritems = db.get(saveditemkeys)
(Nota que você não precisa mesmo da cláusula de guarda - uma db.get em 0 entidades é curto-circuito appropritely.)
Qual é a diferença, você pode perguntar? Bem, um db.get leva cerca 20-40ms. A consulta, por outro lado (GQL ou não) leva cerca de 160-200ms. Mas espere, fica pior! O operador IN é implementado em Python, e se traduz em várias consultas, que são executadas em série. Então, se você faz uma consulta com um filtro IN para 10 teclas, você está fazendo 10 operações de consulta 160ms-ish separadas, para um total de cerca de 1,6 segundos latência. A única db.get, por outro lado, terá o mesmo efeito e tomar um total de cerca de 30ms.
Outras dicas
+1 para Adam por me no caminho certo. Baseado em sua ponteiro, e fazer alguma pesquisa em Code Search, eu tenho a seguinte solução.
usersaveditems = User.Gql(“Select * from UserListOfSavedItems where user =:1”, userkey)
saveditemkeys = []
for item in usersaveditems:
#this should create a list of keys (references) to the saved item table
saveditemkeys.append(item.str())
if len(usersavedsearches > 0):
#and this should get me the items that a user saved
useritems = db.Gql(“SELECT * FROM UniqueListOfSavedItems WHERE __key__ in :1’, saveditemkeys)