简体   繁体   English

合并多个ndb不等式查询的结果

[英]Combining results of multiple ndb inequality queries

The NDB Datastore forbids multiple inequality queries on different properties. NDB数据存储区禁止对不同属性进行多个不平等查询。 To get around this, I thought that the solution might be to combine the results of multiple independent queries. 为了解决这个问题,我认为解决方案可能是合并多个独立查询的结果。 I found this 2011 question which recommends geohashing, with which I am not familiar. 我发现了这个2011年提出的建议进行哈希处理的问题 ,对此我并不熟悉。 So, perhaps there is a better solution today. 因此,今天也许有更好的解决方案。

Consider these two queries: 考虑以下两个查询:

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

I attempt to join them like this: 我试图像这样加入他们:

results = set(q1).intersection(q2)

However, I encounter TypeError: Model is not immutable . 但是,我遇到TypeError: Model is not immutable

My questions: 我的问题:

  • Is there a better way to deal with multiple inequality filters on different properties? 有没有更好的方法来处理不同属性上的多个不等式过滤器?
  • If not, how can I resolve the TypeError above? 如果没有,如何解决上面的TypeError

Thank you for the assistance. 感谢您的帮助。

If you can restructure your User model, you could put in some more properties to make the queries simpler. 如果可以重组User模型,则可以添加更多属性以简化查询。 For example, if you query on the same age ranges, then make a property that encodes the ranges: 例如,如果您在相同的年龄范围内进行查询,则创建一个对范围进行编码的属性:

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

Then you can have: 然后您可以拥有:

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

If your data set is small enough, you can use @TimHoffman's approach: 如果数据集足够小,则可以使用@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))

A more heavyweight approach, that will scale up to big data sets, is the MapReduce library. MapReduce库是一种更重量级的方法,可以扩展到大数据集。 You can put in multiple filters to reduce your data set. 您可以放入多个过滤器以减少数据集。

I had a similar problem. 我有一个类似的问题。 My query was: 我的查询是:

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

But appengine didn't let me do it. 但是appengine不允许我这样做。 So I solved changing one inequality to: 因此,我解决了将一个不等式更改为:

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

Problem solved! 问题解决了! I hope this helps you. 我希望这可以帮助你。

There are two options: 有两种选择:

Change your data models 更改数据模型

Add more properties or adapt the current ones so you can query the object according to the restrictions of the Datastore. 添加更多属性或改编当前属性,以便您可以根据数据存储区的限制查询对象。 This may imply categorizing continuous variables. 这可能意味着对连续变量进行分类。

Find a workaround 寻找解决方法

You can make the most significant query at first and then manually filter the result. 您可以首先进行最重要的查询,然后手动过滤结果。 Have in mind the following considerations: 请注意以下注意事项:

  • You can use projection to make the query more efficient. 您可以使用投影来提高查询效率。
  • Make the results iterable (iter). 使结果可迭代(迭代)。
  • Use get_multi for a list of keys. 使用get_multi作为键列表。

Your code may look like this: 您的代码可能如下所示:

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)

Or 要么

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM