Mongodb - 子文档的键的正则表达式匹配

Mat*_*t P 9 regex lookup mongodb

我有一些文件保存在一个集合(称为urls)中,如下所示:

{
    payload:{
        url_google.com:{
            url:'google.com',
            text:'search'
        }
    }
},
{
    payload:{
        url_t.co:{
            url:'t.co',
            text:'url shortener'
        }
    }
},
{
    payload:{
        url_facebook.com:{
            url:'facebook.com',
            text:'social network'
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用mongo CLI,是否可以查找payload匹配的子文档/^url_/?并且,如果可能的话,是否也可以查询匹配的子文档(例如,确保text存在)?

我在想这样的事情:

db.urls.find({"payload":{"$regex":/^url_/}}).count();
Run Code Online (Sandbox Code Playgroud)

但那是0结果.

任何帮助或建议都会很棒.

谢谢,

马特

dcr*_*sta 6

以这种方式查询文档密钥是不可能的.您可以使用搜索完全匹配$exists,但找不到与模式匹配的键名.

我假设(可能不正确)您正在尝试查找具有URL子文档的文档,并且并非所有文档都具有此文档?为什么不将类型信息推到一个级别,例如:

{
  payload: {
    type: "url",
    url: "Facebook.com",
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以查询如下:

db.foo.find({"payload.type": "url", ...})
Run Code Online (Sandbox Code Playgroud)

如果我没有注意到你不应该使用dot(.)是MongoDB中的关键名称,我也会失职.在某些情况下,可以创建这样的文档,但是当您尝试查询嵌入文档时,它会引起很大的混淆(Mongo使用dot作为"路径分隔符").


Fab*_*ian 5

您可以这样做,但需要使用聚合:聚合是管道,其中每个阶段都应用于每个文档。您有广泛的阶段来执行各种任务。

我为这个特定问题编写了一个聚合管道。如果您不需要计数但需要文档本身,您可能想看看舞台$replaceRoot

编辑:这仅适用于 Mongo v3.4.4 及以上版本(感谢@hwase0ng 的提示)

db.getCollection('urls').aggregate([
    {
        // creating a nested array with keys and values
        // of the payload subdocument.
        // all other fields of the original document
        // are removed and only the filed arrayofkeyvalue persists
        "$project": {
            "arrayofkeyvalue": {
                "$objectToArray": "$$ROOT.payload"
            }
        }
    },
    {
        "$project": {
            // extract only the keys of the array
            "urlKeys": "$arrayofkeyvalue.k"
        }
    },
    {
        // merge all documents
        "$group": {
            // _id is mandatory and can be set
            // in our case to any value
            "_id": 1,
            // create one big (unfortunately double
            // nested) array with the keys
            "urls": {
                "$push": "$urlKeys"
            }
        }
    },
    {
        // "explode" the array and create
        // one document for each entry
        "$unwind": "$urls"
    },
    {
        // "explode" again as the arry
        // is nested twice ...
        "$unwind": "$urls"
    },
    {
        // now "query" the documents
        // with your regex
        "$match": {
            "urls": {
                "$regex": /url_/
            }
        }
    },
    {
      // finally count the number of
      // matched documents
        "$count": "count"
    }
])
Run Code Online (Sandbox Code Playgroud)