gpt4 book ai didi

faunadb - 如何在动物群中按多个条件查询?

转载 作者:行者123 更新时间:2023-12-03 15:15:37 24 4
gpt4 key购买 nike

我试图增进对FaunaDB的理解。

我有一个包含如下记录的集合:

{
"ref": Ref(Collection("regions"), "261442015390073344"),
"ts": 1587576285055000,
"data": {
"name": "italy",
"attributes": {
"amenities": {
"camping": 1,
"swimming": 7,
"hiking": 3,
"culture": 7,
"nightlife": 10,
"budget": 6
}
}
}
}

我想以灵活的方式通过不同的属性进行查询,例如:
  • data.attributes.amenities.camping> 5
  • data.attributes.amenities.camping> 5 AND data.attributes.amenities.hiking> 6
  • data.attributes.amenities.camping <6 AND data.attributes.amenities.culture> 6 AND远足> 5 AND ...

  • 我创建了一个包含所有属性的索引,但是我不知道如何在包含多个术语的索引中执行更大的等于过滤。

    我的后备方法是为每个属性创建一个索引,并使用Intersection获取要检查的所有子查询中的记录,但是这感觉有点不对劲:

    查询:预算> = 6 AND露营> = 8将为:
    Index:
    {
    name: "all_regions_by_all_attributes",
    unique: false,
    serialized: true,
    source: "regions",
    terms: [],
    values: [
    {
    field: ["data", "attributes", "amenities", "culture"]
    },
    {
    field: ["data", "attributes", "amenities", "hiking"]
    },
    {
    field: ["data", "attributes", "amenities", "swimming"]
    },
    {
    field: ["data", "attributes", "amenities", "budget"]
    },
    {
    field: ["data", "attributes", "amenities", "nightlife"]
    },
    {
    field: ["data", "attributes", "amenities", "camping"]
    },
    {
    field: ["ref"]
    }
    ]
    }

    询问:
    Map(
    Paginate(
    Intersection(
    Range(Match(Index("all_regions_by_all_attributes")), [0, 0, 0, 6, 0, 8], [10, 10, 10, 10, 10, 10]),
    )

    ),
    Lambda(
    ["culture", "hiking", "swimming", "budget", "nightlife", "camping", "ref"],
    Get(Var("ref"))
    )
    )

    这种方法具有以下缺点:
  • 它不能像预期的那样工作,例如,如果第一个(文化)属性在此范围内,但第二个(远足)属性不在此范围内,那么我仍然会得到返回值
  • 由于需要针对每个结果进行引用,因此导致大量读取。

  • 是否可以在包含所有数据的这种索引中存储所有值?我知道我可以在索引中添加更多值并访问它们。但这意味着一旦我们向实体添加更多字段,我就必须创建一个新索引。但这也许是平常的事情。

    提前致谢

    最佳答案

    我认为有一些误解使您误入歧途。最重要的一个:Match(Index($x))生成一个集合引用,它是一个有序的元组集合。元组对应于索引的values部分中存在的字段数组。默认情况下,这将是一个单元组,其中包含对索引选择的集合中文档的引用。 Range在集合引用上操作,对用于选择返回的集合ref的术语一无所知。那么我们如何构成查询呢?

    从第一原则开始。让我们想象一下我们刚刚在内存中有了这些东西。如果我们有一组按属性排序的(属性,分数),则得分,然后仅获取那些attribute == $attribute将使我们接近的对象,然后按score > $score进行过滤将使我们得到我们想要的东西。假设我们将属性值对建模为文档,这恰好对应于以属性为项的分数范围查询。我们还可以将指针嵌入到该位置,以便我们也可以在同一查询中对其进行检索。足够的,不休,让我们去做:

    第一站:我们的收藏。

    jnr> CreateCollection({name: "place_attribute"})
    {
    ref: Collection("place_attribute"),
    ts: 1588528443250000,
    history_days: 30,
    name: 'place_attribute'
    }
    jnr> CreateCollection({name: "place"})
    {
    ref: Collection("place"),
    ts: 1588528453350000,
    history_days: 30,
    name: 'place'
    }

    接下来一些数据。我们将选择几个地方,并为其赋予一些属性。
    jnr> Create(Collection("place"), {data: {"name": "mullion"}})
    jnr> Create(Collection("place"), {data: {"name": "church cove"}})
    jnr> Create(Collection("place_attribute"), {data: {"attribute": "swimming", "score": 3, "place": Ref(Collection("place"), 264525084639625739)}})
    jnr> Create(Collection("place_attribute"), {data: {"attribute": "hiking", "score": 1, "place": Ref(Collection("place"), 264525084639625739)}})
    jnr> Create(Collection("place_attribute"), {data: {"attribute": "hiking", "score": 7, "place": Ref(Collection("place"), 264525091487875586)}})

    现在来看更有趣的部分。索引。
    jnr> CreateIndex({name: "attr_score", source: Collection("place_attribute"), terms:[{"field":["data", "attribute"]}], values:[{"field": ["data", "score"]}, {"field": ["data", "place"]}]})
    {
    ref: Index("attr_score"),
    ts: 1588529816460000,
    active: true,
    serialized: true,
    name: 'attr_score',
    source: Collection("place_attribute"),
    terms: [ { field: [ 'data', 'attribute' ] } ],
    values: [ { field: [ 'data', 'score' ] }, { field: [ 'data', 'place' ] } ],
    partitions: 1
    }

    好的。一个简单的查询。谁有远足?
    jnr> Paginate(Match(Index("attr_score"), "hiking"))
    {
    data: [
    [ 1, Ref(Collection("place"), "264525084639625730") ],
    [ 7, Ref(Collection("place"), "264525091487875600") ]
    ]
    }

    没有太多的想象力,一个人可以潜入Get调用以将其撤出。

    那只有5分以上的徒步旅行怎么样?我们有一组有序的元组,因此仅提供第一个成分(分数)就足以获取我们想要的东西。
    jnr> Paginate(Range(Match(Index("attr_score"), "hiking"), [5], null))
    { data: [ [ 7, Ref(Collection("place"), "264525091487875600") ] ] }


    复合条件呢? 5岁以下徒步旅行和游泳(任何成绩)。这是事情发生一些转变的地方。我们要对连接进行建模,这在动物区系中意味着相交的集合。我们的问题是直到现在,我们一直在使用返回分数和位置引用的索引。为了使交叉路口正常工作,我们只需要裁判。巧手的时间:
    jnr> Get(Index("doc_by_doc"))
    {
    ref: Index("doc_by_doc"),
    ts: 1588530936380000,
    active: true,
    serialized: true,
    name: 'doc_by_doc',
    source: Collection("place"),
    terms: [ { field: [ 'ref' ] } ],
    partitions: 1
    }

    您问这样的索引有什么意义?好吧,我们可以使用它从任何索引中删除我们喜欢的任何数据,并通过连接仅保留引用。这样我们得到的地方裁判的远足得分小于5(空数组排在任何东西之前,因此可以充当下限的占位符)。
    jnr> Paginate(Join(Range(Match(Index("attr_score"), "hiking"), [], [5]), Lambda(["s", "p"], Match(Index("doc_by_doc"), Var("p")))))
    { data: [ Ref(Collection("place"), "264525084639625739") ] }

    所以最后一点就是抗拒:所有带有 swimming and (hiking < 5)的地方:
    jnr> Let({
    ... hiking: Join(Range(Match(Index("attr_score"), "hiking"), [], [5]), Lambda(["s", "p"], Match(Index("doc_by_doc"), Var("p")))),
    ... swimming: Join(Match(Index("attr_score"), "swimming"), Lambda(["s", "p"], Match(Index("doc_by_doc"), Var("p"))))
    ... },
    ... Map(Paginate(Intersection(Var("hiking"), Var("swimming"))), Lambda("ref", Get(Var("ref"))))
    ... )
    {
    data: [
    {
    ref: Ref(Collection("place"), "264525084639625739"),
    ts: 1588529629270000,
    data: { name: 'mullion' }
    }
    ]
    }

    多田可以通过几个udfs来解决这个问题,留给读者练习。涉及 or的条件可以用联合方式进行管理。

    关于faunadb - 如何在动物群中按多个条件查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61509089/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com