【问题标题】:NDB querying a GenericProperty in repeated Expando StructuredPropertyNDB 在重复的 Expando StructuredProperty 中查询 GenericProperty
【发布时间】:2012-11-29 18:02:23
【问题描述】:

大家好,我想弄清楚如何为以下案例构建我的查询

首先我定义了一个模型

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", ]

感谢您的帮助

【问题讨论】:

  • 你试过Item.query(ndb.GenericProperty('variants.dynamic') == 'a')吗?
  • 尝试实例化ndb.GenericProperty('variants.dynamic') 会导致ValueError: Name 'variants.dynamic' cannot contain period charactersndb/model.py 第765 行。看来这应该是一个功能请求。

标签: google-app-engine python-2.7 app-engine-ndb


【解决方案1】:

使用 GQL 很容易:

Item.gql("WHERE variants.dynamic = 'a'").fetch()

这也有效:

s = StringProperty()
s._name = 'variants.dynamic')
Item.query(s == 'a').fetch()

请提交功能请求;然而,这将是一个平衡的行为。你想用什么语法?

更新:

同样的事情也适用于 GenericProperty() 或任何其他 Property 子类。

GenericProperty('variants.dynamic') 被禁止的原因是为了防止人们做这样的黑客攻击:

class MyHack(ndb.Model):
  foo = StringProperty('bar.baz')

这会混淆序列化和反序列化代码。

也许我们可以向 Property 添加一个标志来跳过此检查,但随后不允许在模型定义中使用该属性(它只允许在查询中使用它)。

或者也许我们可以完成这项工作(但我认为这会很困难):

Item.query(Item.variants.dynamic == 'a').fetch()

(仅当变体是 Expando 时)。

【讨论】:

  • Dang 完全忘记了 gql,这当然是一个简单的解决方案。我认为正确的语法是 GenericProperty("variants.dynamic") 因为目标属性毕竟是 GenericProperty。您的示例适用于任何类型还是仅适用于字符串?
  • 最后一个解决方案对我不起作用,因为我必须从字符串中引用该属性。
【解决方案2】:

你可以用一点魔法来做到这一点。

简短回答

variants_dynamic_property = ndb.GenericProperty()
variants_dynamic_property._name = 'variants.dynamic'
q = Item.query(variants_dynamic_property == 'a')

长答案

由于您要查询GenericProperty,因此您需要创建一个docs 状态,例如:

FlexEmployee.query(ndb.GenericProperty('location') == 'SF')

同样,当查询StucturedPropertydocs 状态时,您可以使用该属性的一个属性,例如:

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'

【讨论】:

  • 这不等同于 Item.query(ndb.query.FilterNode("variants.%s" % dynamic, "=", "a")) 吗?你有没有测试过这是否真的有效?
  • 是的,它确实有效,但我在写完这篇文章后痛苦地发现,不适用于repeated 属性。我还在努力。我不确定这两者是否等价,但它们很可能是等价的。
【解决方案3】:

黑客解决方案

临时解决方案:使用ComputedProperty 查询 - 在我们的例子中:

(在模型定义中添加以下内容)

computed_prop = ndb.ComputedProperty(lambda self: self.repeating_prop[0].sub_prop if self.repeating_prop else None)

【讨论】:

    猜你喜欢
    • 2019-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-20
    相关资源
    最近更新 更多