Google app engine NDB在重复Expando StructuredProperty中查询GenericProperty
嘿,伙计们,我正试图找出如何为下面的案例构造我的查询 首先我定义了一个模型Google app engine NDB在重复Expando StructuredProperty中查询GenericProperty,google-app-engine,python-2.7,app-engine-ndb,Google App Engine,Python 2.7,App Engine Ndb,嘿,伙计们,我正试图找出如何为下面的案例构造我的查询 首先我定义了一个模型 class Variant(ndb.Expando): test = ndb.StringProperty() class Item(ndb.Model): test2 = ndb.StringProperty() variants = ndb.StructuredProperty(Variant, repeated=True) variant = Variant(test="test",
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()
然后是查询的东西。。到目前为止我已经试过了
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")
这些都不管用。。这应该是完全可能的,因为数据存储中的属性名称是
variants.dynamic = ["a", ]
谢谢你的帮助你可以用一点魔法做到这一点 简短回答:
variants_dynamic_property = ndb.GenericProperty()
variants_dynamic_property._name = 'variants.dynamic'
q = Item.query(variants_dynamic_property == 'a')
长答案:
variants_dynamic_property = ndb.GenericProperty()
variants_dynamic_property._name = 'variants.dynamic'
q = Item.query(variants_dynamic_property == 'a')
由于您正在查询GenericProperty
,因此需要创建一个作为状态,例如:
FlexEmployee.query(ndb.GenericProperty('location') == 'SF')
类似地,在查询结构化属性时,可以使用属性属性的状态,例如:
Contact.query(Contact.address.city == 'Amsterdam')
所以结合这些,你需要
Item.query(ndb.GenericProperty('variants.dynamic') == 'a')
但是尝试通过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
但是,您可以通过使用没有属性名称的构造函数,然后在事实之后设置名称来解决此问题:
variants_dynamic_property = ndb.GenericProperty()
variants_dynamic_property._name = 'variants.dynamic'
使用GQL很容易:
Item.gql("WHERE variants.dynamic = 'a'").fetch()
这也适用于:
s = StringProperty()
s._name = 'variants.dynamic')
Item.query(s == 'a').fetch()
请提交功能请求;然而,这将是一个平衡的行动。您希望使用什么语法
更新:
这同样适用于GenericProperty()或任何其他属性子类
禁止GenericProperty('variants.dynamic')的原因是为了防止人们进行这样的黑客行为:
class MyHack(ndb.Model):
foo = StringProperty('bar.baz')
这将混淆序列化和反序列化代码
也许我们可以向属性添加一个标志,该标志跳过此检查,但不允许在模型定义中使用该属性(它只允许在查询中使用)
或者我们可以做到这一点(我认为这很难做到):
(仅当变体是Expando时)。黑客解决方案:
variants_dynamic_property = ndb.GenericProperty()
variants_dynamic_property._name = 'variants.dynamic'
q = Item.query(variants_dynamic_property == 'a')
临时解决方案:使用ComputedProperty
查询-在本例中:
(将以下内容添加到模型定义中)
您是否尝试过Item.query(ndb.GenericProperty('variants.dynamic')=='a')
?尝试实例化ndb.GenericProperty('variants.dynamic')
会导致ValueError:Name'variants.dynamic'不能包含ndb/model.py
第765行中的句点字符。这似乎应该是一个功能请求。这不是等同于Item.query(ndb.query.FilterNode(“变体。%s”%dynamic,“=”,“a”)?你测试过这是否真的有效吗?是的,它确实有效,但正如我在写下这篇文章后痛苦地发现的,不是针对重复的属性。我还在努力。我不确定这两者是否相等,但它们很可能是相等的。当已经完全忘记了gql,这当然是一个简单的解决方案。我认为正确的语法应该是GenericProperty(“variants.dynamic”),因为目标属性毕竟是GenericProperty。您的示例适用于任何类型还是仅适用于字符串?最后一个解决方案不适用于我,因为我必须从字符串引用属性。