【问题标题】:NDB query with projection on an attribute used in .IN()NDB 查询与 .IN() 中使用的属性的投影
【发布时间】:2017-09-14 20:17:52
【问题描述】:

假设我有一个模型:

class Pet(ndb.Model):
    age = ndb.IntegerProperty(indexed=False)
    name = ndb.StringProperty(indexed=True)
    owner = ndb.KeyProperty(indexed=True)

我有一个名为owners 的键列表。要查询Pets,我会这样做:

pets = Pets.query(Pets.owner.IN(owners)).fetch()

问题是这个查询返回了整个实体。

如何进行计划查询并仅获取所有者和名称?

或者我应该如何构造数据以获取名称和所有者。

我可以为name 做一个投影,但我失去了宠物对主人的参考。而owner 不能在投影中。

【问题讨论】:

  • 它总是按设计返回整个实体(对象)
  • 请为我澄清你的问题,因为如果你有一个钥匙列表。你可以打电话给(key).get(),它会带来entity,你可以选择你想要的属性。在应用引擎中也可以免费通过密钥获取实体!

标签: google-app-engine google-cloud-datastore google-app-engine-python


【解决方案1】:

正如您所注意到的,您无法在您提到的确切上下文中执行此操作,因为您点击了 Limitations on projections 之一:

  • 无法投影在相等 (=) 或成员资格 (IN) 过滤器中引用的属性。

由于owner 用于IN 过滤器,因此无法投影。由于您需要 owner 并且无法投影它,因此您必须放弃投影,因此您将始终获得整个实体。

另一种方法是将您的实体拆分为 2 个对等实体,始终保持 1:1 的关系,使用相同的实体 ID:

class PetA(ndb.Model):
    name = ndb.StringProperty(indexed=True)
    owner = ndb.KeyProperty(indexed=True)

class PetB(ndb.Model):
    age = ndb.IntegerProperty(indexed=False)

通过这种方式,您可以执行相同的查询,除了在 PetA 种类而不是原始的 Pet 上,您得到的结果将与您正在寻找的原始投影查询等效。

不幸的是,这仅适用于同一实体的一个或极少数此类投影查询,否则您需要将实体拆分为太多部分。所以你可能不得不妥协。

您可以在re-using an entity's ID for other entities of different kinds - sane idea?找到更多关于实体拆分的详细信息

【讨论】:

  • 嗯,有趣的想法。谢谢。但是如果宠物只包含我需要的数据,你会说只索引owner 是个好主意吗?名字不是必须的,对吧?没有查询名称
  • 仅当您想按name 过滤或排序查询结果时才需要索引name
猜你喜欢
  • 1970-01-01
  • 2012-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-17
  • 1970-01-01
相关资源
最近更新 更多