【问题标题】:Mongodb - regex match of keys for subdocumentsMongodb - 子文档键的正则表达式匹配
【发布时间】:2023-03-24 22:33:01
【问题描述】:

我有一些文档保存在一个集合(称为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'
        }
    }
}

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

我在想这样的事情:

db.urls.find({"payload":{"$regex":/^url_/}}).count();

但这会返回 0 个结果。

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

谢谢,

马特

【问题讨论】:

    标签: regex mongodb lookup


    【解决方案1】:

    无法以这种方式查询文档键。您可以使用$exists 搜索完全匹配,但找不到匹配模式的键名。

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

    {
      payload: {
        type: "url",
        url: "Facebook.com",
        ...
      }
    }
    

    然后你可以像这样查询:

    db.foo.find({"payload.type": "url", ...})
    

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

    【讨论】:

    • 感谢您的回答。不幸的是,我无法控制插入到集合中的文档的设计:/ 另外,我不确定您所说的嵌入文档是什么意思?你有链接吗?这和子对象一样吗?
    • 我认为它的含义与您所说的“子对象”相同。 “嵌入式文档”是一个更以数据为中心的术语,而“子对象”是一个更以编程为中心的术语(对于那些将 Mongo 文档表示为对象层次结构的语言)。如果您无法更改集合中文档的结构,您可以考虑使用 map-reduce 将它们重写为更可查询的格式(例如我在此处提出的格式)
    【解决方案2】:

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

    我为这个特定问题编写了一个聚合管道。如果您不需要计数而是文档本身,您可能需要查看$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"
        }
    ])
    

    【讨论】:

    • 值得一提的是,这只适用于 mongo db v3.4.4 及更高版本...太糟糕了,我正在使用 v3.2
    猜你喜欢
    • 2017-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多