Google App Engine 数据存储 - 在投影和过滤器中使用 StructuredProperty 进行查询
Google App Engine Datastore - query with StructuredProperty in projection and filter
我有几个 ndb 模型如下所示:
class Product(ndb.Model):
manufacturer = ndb.StringProperty()
category = ndb.StringProperty()
price = ndb.FloatProperty()
class Customer(ndb.Model):
customerId = ndb.StringProperty()
name = ndb.StringProperty()
products = ndb.StructuredProperty(Product, repeated=True)
并且我想根据 he/she 拥有的产品的 'manufacturer' 和 'category' 进行查询。所以这个查询按预期工作。
query = Customer.query(Customer.products == Product(manufacturer=data_json["product"]["manufacturer"],
category=data_json["product"]["category"]))
results= query.fetch()
但是,我无法让 "projection" 与此查询一起使用。以下查询只是 return 什么也没做。
query = Customer.query(Customer.products == Product(manufacturer=data_json["product"]["manufacturer"],
category=data_json["product"]["category"]))
results= query.fetch(projection=[Customer.products.price])
但是如果我使用没有过滤器的投影,投影部分工作正常。以下查询将 return 所有实体,但仅 'price' 属性
results= Customer.query().fetch(projection=[Customer.products.price])
有什么想法吗?谢谢。
顺便说一句,我的查询是基于这篇文章开发的。
https://cloud.google.com/appengine/docs/standard/python/ndb/queries#filtering_structured_properties
在 ndb 库中记录了组合 AND 和 OR 操作的正确方法在 NDB Client Library's documentation.
对于下面的查询,您正在过滤器中执行 AND 运算,因此您应该使用我在下面建议的那个,而不是这个,使用 ndb.AND().
# Your query
query = Customer.query(Customer.products == Product(manufacturer=data_json["product"]["manufacturer"], category=data_json["product"]["category"]))
# Query using ndb.AND
query = Customer.query(ndb.AND(Customer.products == Product(manufacturer=data_json["product"]["manufacturer"]), Customer.products == Product(category=data_json["product"]["category"])))
此外,事实证明,如果您执行 filtering in multiple steps,查询也有效:
# Your request
query = Customer.query(Customer.products == Product(manufacturer=data_json["product"]["manufacturer"], category=data_json["product"]["category"]))
results = query.fetch(projection=[Customer.products.price])
# Request performing filter in multiple steps
query = Customer.query(Customer.products == Product(category=data_json["product"]["category"]))
query1 = query.filter(Customer.products == Product(manufacturer=data_json["product"]["manufacturer"]))
results = query1.fetch(projection=[Customer.products.price])
你可以使用任何一个建议的替代方案,尽管我建议使用 ndb.AND() 因为它最小化了代码并且也是结合 AND 的最佳方式操作。
UPDATE 一些代码:
app.yaml
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /.*
script: main.app
main.py
import webapp2
from google.appengine.ext import ndb
# Datastore Models
class Product(ndb.Model):
manufacturer = ndb.StringProperty()
category = ndb.StringProperty()
price = ndb.FloatProperty()
class Customer(ndb.Model):
customerId = ndb.StringProperty()
name = ndb.StringProperty()
products = ndb.StructuredProperty(Product, repeated=True)
# Create entities for testing purposes
class CreateEntities(webapp2.RequestHandler):
def get(self):
prod1 = Product(manufacturer="Google", category="GCP", price=105.55)
prod2 = Product(manufacturer="Google", category="GCP", price=123.45)
prod3 = Product(manufacturer="Google", category="Drive", price=10.38)
prod1.put()
prod2.put()
prod3.put()
cust1 = Customer(customerId="Customer1", name="Someone", products=[prod1,prod2,prod3])
cust2 = Customer(customerId="Customer2", name="Someone else", products=[prod1])
cust3 = Customer(customerId="Customer3", name="Noone", products=[prod3])
cust1.put()
cust2.put()
cust3.put()
# Response text
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('Done creating entities')
class GetEntities(webapp2.RequestHandler):
def get(self):
# This will not work
#query = Customer.query(Customer.products == Product(category="GCP", manufacturer="Google"))
#results = query.fetch(projection=[Customer.products.price])
# Alternative 1 - WORKS
#query = Customer.query(Customer.products == Product(category="GCP"))
#query1 = query.filter(Customer.products == Product(manufacturer="Google"))
#results = query1.fetch(projection=[Customer.products.price])
# Alternative 2 - WORKS
query = Customer.query(ndb.AND(Customer.products == Product(manufacturer="Google"), Customer.products == Product(category="GCP")))
results = query.fetch(projection=[Customer.products.price])
self.response.out.write('<html><body>')
for result in results:
self.response.out.write("%s<br><br>" % result)
self.response.out.write('</body></html>')
app = webapp2.WSGIApplication([
('/createEntities', CreateEntities),
('/getEntities', GetEntities),
], debug=True)
我有几个 ndb 模型如下所示:
class Product(ndb.Model):
manufacturer = ndb.StringProperty()
category = ndb.StringProperty()
price = ndb.FloatProperty()
class Customer(ndb.Model):
customerId = ndb.StringProperty()
name = ndb.StringProperty()
products = ndb.StructuredProperty(Product, repeated=True)
并且我想根据 he/she 拥有的产品的 'manufacturer' 和 'category' 进行查询。所以这个查询按预期工作。
query = Customer.query(Customer.products == Product(manufacturer=data_json["product"]["manufacturer"],
category=data_json["product"]["category"]))
results= query.fetch()
但是,我无法让 "projection" 与此查询一起使用。以下查询只是 return 什么也没做。
query = Customer.query(Customer.products == Product(manufacturer=data_json["product"]["manufacturer"],
category=data_json["product"]["category"]))
results= query.fetch(projection=[Customer.products.price])
但是如果我使用没有过滤器的投影,投影部分工作正常。以下查询将 return 所有实体,但仅 'price' 属性
results= Customer.query().fetch(projection=[Customer.products.price])
有什么想法吗?谢谢。
顺便说一句,我的查询是基于这篇文章开发的。 https://cloud.google.com/appengine/docs/standard/python/ndb/queries#filtering_structured_properties
在 ndb 库中记录了组合 AND 和 OR 操作的正确方法在 NDB Client Library's documentation.
对于下面的查询,您正在过滤器中执行 AND 运算,因此您应该使用我在下面建议的那个,而不是这个,使用 ndb.AND().
# Your query
query = Customer.query(Customer.products == Product(manufacturer=data_json["product"]["manufacturer"], category=data_json["product"]["category"]))
# Query using ndb.AND
query = Customer.query(ndb.AND(Customer.products == Product(manufacturer=data_json["product"]["manufacturer"]), Customer.products == Product(category=data_json["product"]["category"])))
此外,事实证明,如果您执行 filtering in multiple steps,查询也有效:
# Your request
query = Customer.query(Customer.products == Product(manufacturer=data_json["product"]["manufacturer"], category=data_json["product"]["category"]))
results = query.fetch(projection=[Customer.products.price])
# Request performing filter in multiple steps
query = Customer.query(Customer.products == Product(category=data_json["product"]["category"]))
query1 = query.filter(Customer.products == Product(manufacturer=data_json["product"]["manufacturer"]))
results = query1.fetch(projection=[Customer.products.price])
你可以使用任何一个建议的替代方案,尽管我建议使用 ndb.AND() 因为它最小化了代码并且也是结合 AND 的最佳方式操作。
UPDATE 一些代码:
app.yaml
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /.*
script: main.app
main.py
import webapp2
from google.appengine.ext import ndb
# Datastore Models
class Product(ndb.Model):
manufacturer = ndb.StringProperty()
category = ndb.StringProperty()
price = ndb.FloatProperty()
class Customer(ndb.Model):
customerId = ndb.StringProperty()
name = ndb.StringProperty()
products = ndb.StructuredProperty(Product, repeated=True)
# Create entities for testing purposes
class CreateEntities(webapp2.RequestHandler):
def get(self):
prod1 = Product(manufacturer="Google", category="GCP", price=105.55)
prod2 = Product(manufacturer="Google", category="GCP", price=123.45)
prod3 = Product(manufacturer="Google", category="Drive", price=10.38)
prod1.put()
prod2.put()
prod3.put()
cust1 = Customer(customerId="Customer1", name="Someone", products=[prod1,prod2,prod3])
cust2 = Customer(customerId="Customer2", name="Someone else", products=[prod1])
cust3 = Customer(customerId="Customer3", name="Noone", products=[prod3])
cust1.put()
cust2.put()
cust3.put()
# Response text
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('Done creating entities')
class GetEntities(webapp2.RequestHandler):
def get(self):
# This will not work
#query = Customer.query(Customer.products == Product(category="GCP", manufacturer="Google"))
#results = query.fetch(projection=[Customer.products.price])
# Alternative 1 - WORKS
#query = Customer.query(Customer.products == Product(category="GCP"))
#query1 = query.filter(Customer.products == Product(manufacturer="Google"))
#results = query1.fetch(projection=[Customer.products.price])
# Alternative 2 - WORKS
query = Customer.query(ndb.AND(Customer.products == Product(manufacturer="Google"), Customer.products == Product(category="GCP")))
results = query.fetch(projection=[Customer.products.price])
self.response.out.write('<html><body>')
for result in results:
self.response.out.write("%s<br><br>" % result)
self.response.out.write('</body></html>')
app = webapp2.WSGIApplication([
('/createEntities', CreateEntities),
('/getEntities', GetEntities),
], debug=True)