【问题标题】:How can I query for direct descendants only?如何仅查询直系后代?
【发布时间】:2012-04-30 10:33:27
【问题描述】:

假设我有相同类型的实体a、b和c,情况是这样的:

实体 a 是实体 b 的父级 实体 b 是实体 c 的父级

现在如果我执行以下查询

query = ndb.Query(ancestor=a.key)
result = query.fetch()

结果将同时包含 b 和 c 实体。有没有办法可以过滤掉 c 以便只保留直接后代的实体?除了我检查结果并删除它们之外的任何方式。

【问题讨论】:

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


    【解决方案1】:

    这样做的唯一方法是修改您的架构,添加引用实体直接父级的“父级”KeyProperty,然后对其进行过滤。

    【讨论】:

    • 还要注意,祖先查询的结果实际上也将包含一个(假设它们都具有相同的种类)。您还可以在每个实体中拥有一个“级别”属性,其中根的级别为 0,其直接子级的级别为 1,其子级的级别为 2,等等。
    【解决方案2】:

    实际上,这根本不支持。尼克的回答确实有效,但前提是您可以在查询中指定 OP 未指定的实体类型:

    “Kindless 查询不能包含属性过滤器。但是,它们可以通过传递 Entity.KEY_RESERVED_PROPERTY 作为过滤器的属性名称来按实体键进行过滤。还支持对 Entity.KEY_RESERVED_PROPERTY 进行升序排序。”

    【讨论】:

    • 我正在使用尼克的答案,它工作正常。不过我不得不转向多边形模型。
    • @sorin7486 那么,您是说您已经成功地执行了包含过滤器但不包含种类的祖先查询?
    • 它确实包含一种类型,只是它是基本类型。我所有的对象都是不同类型的页面,它们都扩展了一个 Page 类。
    【解决方案3】:

    这有点晚了,但它会帮助任何有同样问题的人。

    解决方案是首先进行仅键查询并获取直接后代键的子集。

    使用该键子集,您可以批量获取所需的实体。

    我对python不熟悉,所以这里是go中的一个例子:

    directDescKeys := make([]*datastore.Key, 0)
    
    q := datastore.NewQuery("A").Ancestor(parentKey).KeysOnly()
    for it := q.Run(ctx);; {
        key, err := it.Next(nil)
        if err == datastore.Done {
            break
        } else if err != nil {
            // handle error
        }
    
        if reflect.DeepEquals(key.Parent(), parentKey) {
            directDescKeys = append(directDescKeys, key)
        }
    }
    
    entities := make([]*A, len(directDescKeys))
    if err := datastore.GetMulti(ctx, directDescKeys, entities); err != nil {
        // handle error
    }
    

    【讨论】:

      猜你喜欢
      • 2012-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-09
      • 1970-01-01
      相关资源
      最近更新 更多