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

发布于 2024-12-02 17:19:19 字数 772 浏览 0 评论 0原文

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

Using the mongo CLI, is it possible to find for subdocuments of payload that match /^url_/?而且,如果可能的话,是否也可以查询匹配的子文档(例如,确保 text 存在)?

我在想这样的事情:

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

但这返回了 0 个结果。

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

谢谢,

马特

I have some documents saved in a collection (called urls) that look like this:

{
    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'
        }
    }
}

Using the mongo CLI, is it possible to look for subdocuments of payload that match /^url_/? And, if that's possible, would it also be possible to query on the match's subdocuments (for example, make sure text exists)?

I was thinking something like this:

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

But that's returning 0 results.

Any help or suggestions would be great.

Thanks,

Matt

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

苄①跕圉湢 2024-12-09 17:19:19

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

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

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

然后您可以这样查询:

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

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

It's not possible to query against document keys in this way. You can search for exact matches using $exists, but you cannot find key names that match a pattern.

I assume (perhaps incorrectly) that you're trying to find documents which have a URL sub-document, and that not all documents will have this? Why not push that type information down a level, something like:

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

Then you could query like:

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

I would also be remiss if I did not note that you shouldn't use dots (.) is key names in MongoDB. In some cases it's possible to create documents like this, but it will cause great confusions as you attempt to query into embedded documents (where Mongo uses dot as a "path separator" so to speak).

千と千尋 2024-12-09 17:19:19

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

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

You can do it but you need to use aggregation: Aggregation is pipeline where each stage is applied to each document. You have a wide range of stages to perform various tasks.

I wrote an aggregate pipeline for this specific problem. If you don't need the count but the documents itself you might want to have a look at the $replaceRoot stage.

EDIT: This works only from Mongo v3.4.4 onwards (thanks for the hint @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"
    }
])
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文