0

NDB 数据存储禁止对不同属性的多个不等式查询。为了解决这个问题,我认为解决方案可能是结合多个独立查询的结果。我发现了这个 2011 年的问题,它推荐了 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上述问题?

感谢您的帮助。

4

3 回答 3

2

如果您可以重新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库。您可以放置​​多个过滤器来减少数据集。

于 2015-11-06T18:16:11.193 回答
0

有两种选择:

更改数据模型

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

寻找解决方法

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

  • 您可以使用投影来提高查询效率。
  • 使结果可迭代(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']
于 2017-10-18T21:35:16.440 回答
0

我有一个类似的问题。我的查询是:

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

问题解决了!我希望这可以帮助你。

于 2016-03-31T13:47:49.800 回答