代码之家  ›  专栏  ›  技术社区  ›  Cyker

mongodb:匹配字符串或数组[重复]

  •  0
  • Cyker  · 技术社区  · 7 年前

    我有一个MongoDB集合,包含284.116条tweets。问题是有些对象中的“author”字段属于对象类型,而其他对象中的“author”字段属于数组类型。所以问题是我要过滤哪些是数组,哪些是对象。

    例如: 作者字段的类型为对象。

    {
        "_id" : ObjectId("55edfbd11a87d41d987a6dc1"),
        "tweet" : "Back in my dorm, yay!",
        "uri" : "https://twitter.com/natalylug0/status/640994018529181696",
        "date" : "2015-09-08 00:04:17",
        "country" : "U.S.A.",
        "city" : "Texas",
        "state" : "Dallas",
        "author" : {
            "username" : "Nataly",
            "uri" : "https://twitter.com/natalylug0",
            "screenname" : "natalylug0"
        }
    }
    

    另一个是: 作者字段的类型为数组。

    {
        "_id" : ObjectId("55ee3a00e11fbb1030d659fe"),
        "author" : [ 
            {
                "username" : "Relapsed Shini",
                "uri" : "https://twitter.com/iPictoraL",
                "screenname" : "iPictoraL"
            }
        ],
        "tweet" : "@zumbiezuza 😍😍😍💚 ily zoeeeeeeee",
        "uri" : "https://twitter.com/iPictoraL/status/641060812140900352",
        "date" : "2015-09-08 01:29:42",
        "country" : "U.S.A.",
        "city" : "Texas",
        "state" : "Dallas"
    }
    

    所以我执行了这样的查询:

    db.getCollection('tweets').find({ author: { $type: 4} })
    

    我得到的是

    Fetched 0 record(s) 
    

    但如果执行 $类型:3 我得到284.116个值,这个值与这个集合的大小相同。

    所以我的问题是,如何过滤“author”字段包含数组的对象。

    0 回复  |  直到 9 年前
        1
  •  26
  •   Blakes Seven    11 年前

    实际上,文档中列出了 $type 特别是关于阵列:

    当应用于数组时,$type匹配指定类型的任何内部元素。如果没有投影,这意味着如果任何元素的类型正确,整个数组都将匹配。对于投影,结果将只包含请求类型的元素。

    这意味着,与其检测“元素本身”是否在数组中,实际要测试的是数组的“内部元素”,以查看它是什么类型。

    现在文档本身建议使用 $where :

    .find({ "$where": "return Array.isArray(this.author)" })
    

    但我觉得这很可怕,因为有更好的方法。

    诀窍在里面 "dot notation" ,您在哪里要求 0 数组的索引元素 $exists

    .find({ "author.0": { "$exists": true } })
    

    这只是基本情况,如果“0”元素存在,那么字段就存在,因此数据是一个数组。

    一旦你理解了这个逻辑前提,那么它就是一个非常简单的测试。唯一不能与之匹配的是一个“真正空的”数组,在这种情况下,如果需要的话,您可以返回到JavaScript选项。但这实际上可以使用索引,因此最好使用后一种形式。

        2
  •  5
  •   Ciabaros Wiktor Stribiżew    9 年前

    下面是一种更好的方法来完成您最初的要求;即实际检查某个字段是否包含数组类型值:

    .find({ "author": { "$gte": [] } })
    

    MongoDB的数组$type功能虽然有很好的文档记录,但与所有其他$type检查不一致,显然不适用于这个用例,但是由于大约2.6,您可以使用上面的查询来检查值是否是数组(空的或不空的)。

    我说这比当前选择的答案“更好”,因为不建议通过$where执行代码,除非标准查询构造确实无法完成任务。

    为了详细说明,由于在执行代码中缺乏使用索引的能力,因此不建议使用$where。更多详细信息: https://docs.mongodb.com/manual/reference/operator/query/where/#considerations

    另外,如果要特别检查非空数组,请使用以下命令:

    .find({ "author": { "$gt": [] } })
    

    从技术上讲,这一个比当前答案对应的$exists解决方案更好,因为字段可能有一个名为“0”的非数组对象,并且将匹配为“非空数组”,在这种情况下这是错误的。