[英]NDB querying a GenericProperty in repeated Expando StructuredProperty
Hey guys im trying to figure out how to structure my query for the following case 大家好,我正在尝试找出以下情况的查询结构
First i have a model defined 首先,我定义了一个模型
class Variant(ndb.Expando):
test = ndb.StringProperty()
class Item(ndb.Model):
test2 = ndb.StringProperty()
variants = ndb.StructuredProperty(Variant, repeated=True)
variant = Variant(test="test", dynamic="a")
item = Item(test2="test", variants=[variant, ])
item.put()
and then for the query stuff.. So far i've tried 然后查询的东西..到目前为止,我已经尝试过
dynamic = "dynamic"
Item.query(ndb.GenericProperty("variants.%s" % dynamic) == "a")
Item.query(Item._properties["variants.%s" % dynamic] == "a")
Item.query(getattr(Item.variants, dynamic) == "a")
Item.query(getattr(Item, "variants.%s" % dynamic) == "a")
Item.query(ndb.query.FilterNode("variants.%s" % dynamic, "=", "a"))
generic_prop = ndb.GenericProperty()
generic_prop._name = "variants.%s" % dynamic
Item.query(generic_prop == "a")
and none of these works.. This should be perfectly possible since the property name in the datastore is 而且这些都不起作用。.由于数据存储区中的属性名称为
variants.dynamic = ["a", ]
Thank you for your help 谢谢您的帮助
It's easy using GQL: 使用GQL很容易:
Item.gql("WHERE variants.dynamic = 'a'").fetch()
Also this works: 同样可行:
s = StringProperty()
s._name = 'variants.dynamic')
Item.query(s == 'a').fetch()
Please do file a feature request; 请提交功能请求; however it's going to be a balancing act. 但是这将是一个平衡的行为。 What syntax would you like to use? 您想使用什么语法?
UPDATE: 更新:
The same thing works with GenericProperty(), or any other Property subclass. GenericProperty()或任何其他Property子类也可以使用相同的方法。
The reason that GenericProperty('variants.dynamic') is forbidden is to prevent people from doing hacks like this: 禁止GenericProperty('variants.dynamic')的原因是为了防止人们进行此类黑客攻击:
class MyHack(ndb.Model):
foo = StringProperty('bar.baz')
which will confuse the serialization and deserialization code. 这会混淆序列化和反序列化代码。
Maybe we can add a flag to Property that skips this check but then disallows using the property in a model definition (it would only allow it in a query). 也许我们可以向Property添加一个标志,以跳过此检查,但随后不允许在模型定义中使用该属性(仅允许在查询中使用该属性)。
Or maybe we can make this work (I think this would be hard though): 或者,也许我们可以完成这项工作(不过,我认为这很难):
Item.query(Item.variants.dynamic == 'a').fetch()
(only if variants is an Expando). (仅当变体是Expando时)。
You can do this with a bit of magic. 您可以通过一点魔术来做到这一点。
SHORT ANSWER : 简短答案 :
variants_dynamic_property = ndb.GenericProperty()
variants_dynamic_property._name = 'variants.dynamic'
q = Item.query(variants_dynamic_property == 'a')
LONG ANSWER : 长答案 :
Since you are querying for a GenericProperty
, you'll need to create one as the docs state, eg: 由于您要查询GenericProperty
,因此需要创建一个作为docs状态,例如:
FlexEmployee.query(ndb.GenericProperty('location') == 'SF')
Similarly, when querying for a StucturedProperty
, the docs state you can use a property of the property, eg: 同样,在查询StucturedProperty
, 文档说明您可以使用该属性的属性,例如:
Contact.query(Contact.address.city == 'Amsterdam')
So combining these, you would need 所以结合这些,您将需要
Item.query(ndb.GenericProperty('variants.dynamic') == 'a')
but trying to construct the property via ndb.GenericProperty('variants.dynamic')
results in the following exception: 但是尝试通过ndb.GenericProperty('variants.dynamic')
构造属性会导致以下异常:
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/utils.py", line 136, in positional_wrapper
return wrapped(*args, **kwds)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 2366, in __init__
super(GenericProperty, self).__init__(name=name, **kwds)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/utils.py", line 136, in positional_wrapper
return wrapped(*args, **kwds)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 765, in __init__
raise ValueError('Name %r cannot contain period characters' % (name,))
ValueError: Name 'variants.dynamic' cannot contain period characters
But you can get around this by using the constructor with no property name and then setting the name after the fact: 但是,您可以通过使用不带属性名称的构造函数来解决此问题,然后在事实之后设置名称:
variants_dynamic_property = ndb.GenericProperty()
variants_dynamic_property._name = 'variants.dynamic'
Hackish Solution : 骇客解决方案 :
A temporary solution: Using a ComputedProperty
to query by - in our case: 临时解决方案:在本例中,使用ComputedProperty
进行查询-
(adding the following to the model definition) (在模型定义中添加以下内容)
computed_prop = ndb.ComputedProperty(lambda self: self.repeating_prop[0].sub_prop if self.repeating_prop else None)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.