ArangoDB AQL 中 (n) 个数组的交集 [英] INTERSECTION of (n) arrays in ArangoDB AQL

查看:25
本文介绍了ArangoDB AQL 中 (n) 个数组的交集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

场景是这样的:我有一个包含项目的 ArangoDB 集合,以及另一个包含标签的集合.我正在使用图表,并且我有一个名为包含"的边集合,用于连接项目和标签.一个项目有多个标签.

The scenario is this: I have an ArangoDB collection containing items, and another collection containing tags. I am using a graph, and I have an edge collection called "Contains" connecting the items and tags. An item has multiple tags.

现在我正在尝试搜索包含多个标签的项目.例如.包含摄影"、肖像"和面孔"标签的项目.

Now I am trying to do a search for items containing multiple tags. E.g. items containing the tags "photography", "portrait" and "faces".

我的一般方法是从每个标签顶点开始图遍历并找到与该标签相关的项目.那部分工作正常.我得到了一个项目清单.

My general approach is to start a graph traversal from each of the tag vertices and find the items that relate to that tag. That part works fine. I get a list of items.

但我任务的最后一部分是对所有列表进行交集,以便找到包含所有指定标签的项目.我不知道该怎么做.

But the last part of my task is to make an intersection of all the lists in order to find the items that contain ALL the tags specified. And I cannot work out how to do this.

我想做的是这样的:

let tagnames = SPLIT(@tagnames,',')
let tagcollections = (
    FOR tagname IN tagnames
    LET atag = (FOR t IN tags FILTER LOWER(t.text)==LOWER(tagname) RETURN t)
    let collections = (FOR v IN 1..1 INBOUND atag[0] Contains RETURN v)

    RETURN { tag: atag, collections: collections }
)

RETURN INTERSECTION(tagcollections)

但是,它不起作用:INTERSECTION 函数不适用于单个列表,而是适用于多个项目,例如:INTERSECTION(listA, listB, listC...).

However, it doesn't work: The INTERSECTION function does not work on a single list, but on multiple items, like this: INTERSECTION(listA, listB, listC...).

如何对在 FOR .. RETURN 块中找到的列表进行交集?

How can I make an intersection of the lists found in the FOR .. RETURN block?

推荐答案

ArangoDB 3.0 引入了特殊的 数组比较运算符(ANYALLNONE).ALL IN 可用于测试左侧数组中的每个元素是否也在右侧数组中:

ArangoDB 3.0 introduced special array comparison operators (ANY, ALL, NONE). ALL IN can be used to test if every element in the left-hand side array are also in the right-hand side array:

[ "red", "green", "blue" ] ALL IN [ "purple", "red", "blue", "green" ]
// true

请注意,这些运算符还不能使用索引.给定一个将标签直接嵌入到文档中的数据模型,一种解决方法是使用索引来查找包含其中一个标签的所有文档(例如,取第一个元素,["red","green","blue"][0]) 在没有完整集合扫描的情况下减少结果集,如果其他标签也在列表中,则使用 ALL IN 进行后过滤:

Note that these operators can not use indexes yet. Given a data model that embeds the tags directly into the documents, a workaround is to use an index to find all documents that contain one of the tags (e.g. take the first element, ["red","green","blue"][0]) to reduce the result set without a full collection scan, then post-filter with ALL IN if the other tags are also in the list:

LET tagsToSearchFor = [ "red", "green", "blue" ]
FOR doc IN coll
  FILTER tagsToSearchFor[0] IN doc.tags[*] // array index
  FILTER tagsToSeachFor ALL IN doc.tags
  RETURN doc

ALL IN 也可用于带有单独的标签集合的数据模型,但您将无法使用上述索引.例如:

ALL IN can also be used for your data model with a separate collection for tags, but you will not be able to make use of an index like above. For instance:

FOR doc IN documents
    LET tags = (
        FOR v IN INBOUND doc contains
            RETURN v._key
    )
    FILTER ["red", "green", "blue"] ALL IN tags
    RETURN MERGE(doc, {tags})

或者,如果您想使用标签开始遍历并使用基于交集的方法:

Or if you want to start the traversal with the tags and use an intersection-based approach:

LET startTags = ["red", "green", "blue"] // must exist
LET ids = (
    FOR startTag IN DOCUMENT("tags", startTags)
        RETURN (
            FOR v IN OUTBOUND startTag contains
                RETURN v._id
        )
)
LET docs = APPLY("INTERSECTION", ids)

FOR doc IN DOCUMENT(docs)
    RETURN MERGE(doc, {
        tags: (FOR tag IN INBOUND doc contains RETURN tag._key)

    })

这篇关于ArangoDB AQL 中 (n) 个数组的交集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆