【问题标题】:Combining results of multiple ndb inequality queries组合多个ndb不等式查询的结果
【发布时间】:2015-11-05 16:14:59
【问题描述】:

NDB 数据存储禁止对不同属性进行多次不等式查询。为了解决这个问题,我认为解决方案可能是结合多个独立查询的结果。我发现this 2011 question 推荐geohashing,我对此并不熟悉。所以,也许今天有更好的解决方案。

考虑这两个查询:

q1 = User.query(User.age < 18).fetch()
q2 = User.query(User.city != 'New York City').fetch()

我尝试像这样加入他们:

results = set(q1).intersection(q2)

但是,我遇到TypeError: Model is not immutable

我的问题:

  • 是否有更好的方法来处理不同属性上的多个不等式过滤器?
  • 如果不是,我该如何解决上面的TypeError

感谢您的帮助。

【问题讨论】:

  • 有点。我已经阅读了那个答案,并且很好奇如何组合多个查询,这就是我在这个问题中的部分问题。
  • 只做一个keys查询效率更高,你可以根据keys创建集合,然后只获取唯一的集合。 (尽管 ndb 缓存也会节省效率)但是您发现您无法创建一组模型。所以回到键。

标签: google-app-engine google-cloud-datastore app-engine-ndb endpoints-proto-datastore


【解决方案1】:

如果您可以重构 User 模型,则可以添加更多属性以简化查询。例如,如果您查询相同的年龄范围,则创建一个对范围进行编码的属性:

age_range = ndb.IntegerProperty()    # 0 = 0-17, 1 = 18-29, 2 = 30-39, etc.

那么你可以:

q1 = User.query(User.age_range == 0).query(User.city != 'New York City').fetch()

如果你的数据集足够小,可以使用@TimHoffman 的方法:

q1 = User.query(User.age < 18).fetch(keys_only=True)
q2 = User.query(User.city != 'New York City').fetch(keys_only=True)
results = ndb.get_multi(set(q1).intersection(q2))

MapReduce 库是一种更重量级的方法,可以扩展到大数据集。您可以放置​​多个过滤器来减少您的数据集。

【讨论】:

    【解决方案2】:

    我遇到了类似的问题。我的查询是:

    @classmethod:
    def getUnReadMessages(cls, user, date)
        return cls.query(ndb.AND(cls.created <= date,
                                 cls.receiver_key == user.key,
                                 cls.status != READ))
    

    但 appengine 不让我这样做。所以我解决了将一个不等式更改为:

    @classmethod:
    def getUnReadMessages(cls, user, date)
        return cls.query(ndb.AND(cls.created <= date,
                                 cls.receiver_key == user.key,
                                 ndb.OR(cls.status == SEND,
                                        cls.status == RECEIVED)))
    

    问题解决了!希望对您有所帮助。

    【讨论】:

      【解决方案3】:

      有两种选择:

      更改您的数据模型

      添加更多属性或调整当前属性,以便您可以根据数据存储的限制查询对象。这可能意味着对连续变量进行分类。

      寻找解决方法

      您可以先进行最重要的查询,然后手动过滤结果。请记住以下注意事项:

      • 您可以使用projection 来提高查询效率。
      • 使结果可迭代 (iter)。
      • 使用 get_multi 获取键列表。

      您的代码可能如下所示:

      query_iter = User.query(User.age < 18).iter(projection=[User.city])
      query_keys = [u.key() for u in query_iter if u.city != 'New York City']
      query = ndb.get_multi(query_keys)
      

      或者

      query = [u for u in User.query(User.age < 18).fetch() if u.city != 'New York City']
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-01-31
        • 2023-04-01
        • 2011-10-12
        • 1970-01-01
        • 2019-05-04
        • 2015-04-04
        • 1970-01-01
        相关资源
        最近更新 更多