【问题标题】:Query ArangoDB for Arrays查询数组的 ArangoDB
【发布时间】:2015-01-14 06:05:31
【问题描述】:

我在 java 中查询 ArangoDB 以获取 Arrays 值时遇到问题。 String[] 和 ArrayList 我都试过了,都没有成功。

我的查询:

FOR document IN documents FILTER @categoriesArray IN document.categories[*].title RETURN document

绑定参数:

Map<String, Object> bindVars = new MapBuilder().put("categoriesArray", categoriesArray).get();

categoriesArray 包含一堆字符串。我不确定为什么它没有返回任何结果,因为如果我使用以下方式查询:

FOR document IN documents FILTER "Politics" IN document.categories[*].title RETURN document

我得到了我正在寻找的结果。只是在使用 Array 或 ArrayList 时不会。

我也试过查询:

FOR document IN documents FILTER ["Politics","Law] IN document.categories[*].title RETURN document

为了模拟一个 ArrayList,但这不会返回任何结果。我会使用一堆单独的字符串进行查询,但是太多了,当使用这么长的字符串进行查询时,Java 驱动程序会出错。因此,我必须使用 Array 或 ArrayList 进行查询。

categoriesArray 的一个例子:

["Politics", "Law", "Nature"]

数据库的示例图像:

【问题讨论】:

    标签: arangodb aql


    【解决方案1】:

    原因是IN 运算符通过在右侧数组的每个成员中搜索其左侧的值来工作。

    使用以下查询,如果“Politics”是document.categories[*].title 的成员,这将起作用:

    FOR document IN documents FILTER "Politics" IN document.categories[*].title RETURN document
    

    但是,即使“政治”是document.categories[*].title 的成员,以下查询也不起作用:

    FOR document IN documents FILTER [ "Politics", "Law" ] IN document.categories[*].title RETURN document
    

    这是因为它将在右侧的每个成员中搜索确切的值[ "Politics", "Law" ],而这不会出现。您可能正在寻找的是分别查找 "Politics""Law" 的比较,例如:

    FOR document IN documents 
    LET contained = (
      FOR title IN [ "Politics", "Law" ]   /* or @categoriesArray */
        FILTER title IN document.categories[*].title 
        RETURN title
    )
    FILTER LENGTH(contained) > 0
    RETURN document
    

    【讨论】:

    • LET categories = ["Politics", "Law"]LET cat_length = LENGTH(categories)FILTER cat_length == LENGTH(INTERSECTION(categories, document.categories[*].title)) 怎么样?代码看起来更干净,但不知道性能和内存消耗。或者是否可以在 AQL 中添加对 Sets 的支持?喜欢FILTER SET(["Politics", "Law"]) IN SET(document.categories[*].title)。或者在 JS 中,可以这样做:let arr = ["Law", "Science", "Politics"]; ["Politics","Law"].every(elem =&gt; arr.indexOf(elem) != -1)。 AQL 中的EVERY()SOME() 怎么样? SOME(["Law","Politics"], doc.categories[*].title))
    • 我同意,EVERYSOME 在 AQL 中会很有用。我不确定将它们作为函数提供是否会提供最直观的语法,但可能是最简单的。
    【解决方案2】:

    Arango 也(现在)有 Array Comparison Operators,它允许搜索 ALL INANY INNONE IN

    [ 1, 2, 3 ]  ALL IN  [ 2, 3, 4 ]  // false
    [ 1, 2, 3 ]  ALL IN  [ 1, 2, 3 ]  // true
    [ 1, 2, 3 ]  NONE IN  [ 3 ]       // false
    [ 1, 2, 3 ]  NONE IN  [ 23, 42 ]  // true
    [ 1, 2, 3 ]  ANY IN  [ 4, 5, 6 ]  // false
    [ 1, 2, 3 ]  ANY IN  [ 1, 42 ]    // true
    [ 1, 2, 3 ]  ANY ==  2            // true
    [ 1, 2, 3 ]  ANY ==  4            // false
    [ 1, 2, 3 ]  ANY >  0             // true
    [ 1, 2, 3 ]  ANY <=  1            // true
    [ 1, 2, 3 ]  NONE <  99           // false
    [ 1, 2, 3 ]  NONE >  10           // true
    [ 1, 2, 3 ]  ALL >  2             // false
    [ 1, 2, 3 ]  ALL >  0             // true
    [ 1, 2, 3 ]  ALL >=  3            // false
    ["foo", "bar"]  ALL !=  "moo"     // true
    ["foo", "bar"]  NONE ==  "bar"    // false
    ["foo", "bar"]  ANY ==  "foo"     // true
    

    所以您现在可以按以下方式过滤:

    FOR document IN documents 
        FILTER ["Politics", "Law] ANY IN (document.categories[*].title)[**]
        RETURN document
    

    【讨论】:

      猜你喜欢
      • 2021-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多