簡體   English   中英

NDB在重復的Expando StructuredProperty中查詢GenericProperty

[英]NDB querying a GenericProperty in repeated Expando StructuredProperty

大家好,我正在嘗試找出以下情況的查詢結構

首先,我定義了一個模型

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

謝謝您的幫助

使用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時)。

您可以通過一點魔術來做到這一點。

簡短答案

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')

同樣,在查詢StucturedProperty文檔說明您可以使用該屬性的屬性,例如:

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'

駭客解決方案

臨時解決方案:在本例中,使用ComputedProperty進行查詢-

(在模型定義中添加以下內容)

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM