【问题标题】:NDB Query builder doesn't work as expectedNDB 查询生成器无法按预期工作
【发布时间】:2016-11-19 06:07:51
【问题描述】:

我的应用程序中有以下查询

query = cls.query().filter(cls.taskgroup_id == taskgroup_id, cls.availability == True, cls.task_id > min_task_id).order(cls.task_id) query.fetch(1)

上面的工作正常。 (仅获取与 taskgroup_id 匹配且可用且 task_id > min_task_id 的实体)

但是,当我将查询分解为多个语句时。

query = cls.query()
query.filter(cls.taskgroup_id == taskgroup_id)
query.filter(cls.availability == True)
query.filter(cls.task_id > min_task_id)

它没有按预期工作。

当我运行 [2] 时,查询形成分解为多个语句,它返回给我一个可用性为 False 的实体,并且 task_id 等于 min_task_id。

[2] 没有按预期(或按我预期)工作。我认为这里存在用户错误。想知道它是什么。

【问题讨论】:

    标签: python google-app-engine google-cloud-datastore app-engine-ndb dev-appserver


    【解决方案1】:

    来自Filtering by Property Values(强调我的):

    query = Account.query(Account.userid >= 40, Account.userid < 50)
    

    [...]

    而不是在单个表达式中指定整个查询过滤器, 您可能会发现分步构建它更方便:例如:

    appengine/standard/ndb/queries/snippets.py

    query1 = Account.query()  # Retrieve all Account entitites
    query2 = query1.filter(Account.userid >= 40)  # Filter on userid >= 40
    query3 = query2.filter(Account.userid < 50)  # Filter on userid < 50 too
    

    query3 等价于前面的 query 变量 例子。 注意查询对象是不可变的,所以构造 query2不影响query1query3的构建 不影响query1query2

    换句话说,对于您的示例,query.filter() 语句实际上都没有修改query

    只需将语句的结果分配给局部变量并使用它们来代替,就像在引用的示例中一样。

    【讨论】:

    • 有趣。不知道查询对象是不可变的。想知道这背后的理由是什么。将结果分配给临时变量(尽管可以解决问题),在我看来,这很丑(我可能错了,我想这样做是有充分理由的)。
    • 一方面,它提供了构造一个或多个相关查询的能力,其中添加了一个或多个有条件的过滤器(例如,用户可通过 GUI 配置和选择过滤器)。如果查询不是不可变的查询,则必须在可能复杂的条件逻辑中从头开始构建 - 非 DRY 且更容易出错恕我直言。
    • 有趣。我认为,建议创建临时变量,因为不变性同样容易出错。使用 query1 而不是 query2(query3 = query1.filter() 而不是 query2.filter())的错误是很常见的。由于这是一个逻辑错误,因此调试将花费更多时间如果他们提供一个可变查询对象会更好,就像 Java 提供 StringBuilder(mutable) 以及 String(immutable)
    • 如果您不打算重用任何中间查询,那么每次都使用相同的变量名。
    猜你喜欢
    • 2019-04-12
    • 2018-08-08
    • 1970-01-01
    • 2019-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-19
    • 2018-10-13
    相关资源
    最近更新 更多