mongoDB中的数组内部正则表达式

col*_*ore 7 regex mongodb mongodb-query aggregation-framework

我想在mongodb中使用正则表达式在数组内部进行查询,这些集合包含如下文档:

{
"_id" : ObjectId("53340d07d6429d27e1284c77"),
"company" : "New Company",
"worktypes" : [ 
    {
        "name" : "Pompas",
        "works" : [ 
            {
                "name" : "name 2",
                "code" : "A00011",
                "price" : "22,22"
            }, 
            {
                "name" : "name 3",
                "code" : "A00011",
                "price" : "22,22"
            }, 
            {
                "name" : "name 4",
                "code" : "A00011",
                "price" : "22,22"
            }, 
            {
                "code" : "asdasd",
                "name" : "asdads",
                "price" : "22"
            }, 
            {
                "code" : "yy",
                "name" : "yy",
                "price" : "11"
            }
        ]
    }, 
    {
        "name" : "name 4",
        "works" : [ 
            {
                "code" : "A112",
                "name" : "Nombre",
                "price" : "11,2"
            }
        ]
    },          
    {
        "name" : "ee",
        works":[

            {
                "code" : "aa",
                "name" : "aa",
                "price" : "11"
            }, 
            {
                "code" : "A00112",
                "name" : "Nombre",
                "price" : "12,22"
            }
              ]
    }
]
Run Code Online (Sandbox Code Playgroud)

}

然后我需要按公司名称查找文档,其中的任何工作都与代码或名称工作中的正则表达式相匹配.我有这个:

var companyquery = { "company": "New Company"};
var regQuery = new RegExp('^A0011.*$', 'i');

db.categories.find({$and: [companyquery,
            {$or: [
                {"worktypes.works.$.name": regQuery},
                {"worktypes.works.$.code": regQuery}
            ]}]})
Run Code Online (Sandbox Code Playgroud)

但是不要返回任何结果..我认为错误是尝试用de dot和$搜索数组内部..任何想法?

编辑:

有了这个:

db.categories.find({$and: [{"company":"New Company"},
            {$or: [
                {"worktypes.works.name": {"$regex": "^A00011$|^a00011$"}},
                {"worktypes.works.code": {"$regex": "^A00011$|^a00011$"}}
            ]}]})
Run Code Online (Sandbox Code Playgroud)

这是结果:

{
    "_id" : ObjectId("53340d07d6429d27e1284c77"),
    "company" : "New Company",
    "worktypes" : [ 
        {
            "name" : "Pompas",
            "works" : [ 
                {
                    "name" : "name 2",
                    "code" : "A00011",
                    "price" : "22,22"
                }, 
                {
                    "code" : "aa",
                    "name" : "aa",
                    "price" : "11"
                }, 
                {
                    "code" : "A00112",
                    "name" : "Nombre",
                    "price" : "12,22"
                }, 
                {
                    "code" : "asdasd",
                    "name" : "asdads",
                    "price" : "22"
                }, 
                {
                    "code" : "yy",
                    "name" : "yy",
                    "price" : "11"
                }
            ]
        }, 
        {
            "name" : "name 4",
            "works" : [ 
                {
                    "code" : "A112",
                    "name" : "Nombre",
                    "price" : "11,2"
                }
            ]
        }, 
        {
            "name" : "Bombillos"
        }, 
        {
            "name" : "Pompas"
        }, 
        {
            "name" : "Bombillos 2"
        }, 
        {
            "name" : "Other type"
        }, 
        {
            "name" : "Other new type"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

正则表达式不会将结果确定为好..

Nei*_*unn 5

您正在使用JavaScript本机RegExp对象作为正则表达式,但是对于mongo来说处理它需要作为查询文档的一部分发送的正则表达式,这不是一回事.

此正则表达式将与您想要的值不匹配.它可能实际上是^A0111$完全匹配,但是您的大小写不敏感匹配会导致导致更大扫描可能索引的问题.所以有一种更好的方式来编写它.有关不区分大小写的匹配问题,请参阅文档链接.

$regex改为使用运算符:

db.categories.find({
    "$and": [
        {"company":"New Company"},
        { "$or": [
            { "worktypes.works.name": { "$regex": "^A00011$|^a00011$" }},
            { "worktypes.works.code": { "$regex": "^A00011$|^a00011$" }}
        ]}
    ]
})
Run Code Online (Sandbox Code Playgroud)

此外,位置$占位符对查询无效,它们仅用于投影或更新或查询找到的第一个匹配元素.

但是你的实际问题似乎是你试图只获得一个"匹配"条件的数组元素.你不能这样做,为此.find()你需要使用.aggregate():

db.categories.aggregate([

    // Always makes sense to match the actual documents
    { "$match": {
        "$and": [
            {"company":"New Company"},
            { "$or": [
                { "worktypes.works.name": { "$regex": "^A00011$|^a00011$" }},
                { "worktypes.works.code": { "$regex": "^A00011$|^a00011$" }}
            ]}
        ]
    }},

    // Unwind the worktypes array
    { "$unwind": "$worktypes" },

    // Unwind the works array
    { "$unwind": "$worktypes.works" },

    // Then use match to filter only the matching entries
    { "$match": {
       "$or": [
            { "worktypes.works.name": { "$regex": "^A00011$|^a00011$" } },
            { "worktypes.works.code": { "$regex": "^A00011$|^a00011$" } }
        ]
    }},

    /* Stop */
    // If you "really" need the arrays back then include all the following
    // Otherwise the steps up to here actually got you your results

    // First put the "works" array back together
    { "$group": {
        "_id": {
            "_id": "$_id",
            "company": "$company",
            "workname": "$worktypes.name"
        },
        "works": { "$push": "$worktypes.works" }
    }},

    // Then put the "worktypes" array back
    { "$group": {
        "_id": "$_id._id",
        "company": { "$first": "$_id.company" },
        "worktypes": {
            "$push": {
                "name": "$_id.workname",
                "works": "$works"
            } 
        } 
    }}
])
Run Code Online (Sandbox Code Playgroud)

那么.aggregate()所有这些阶段的作用是将数组元素分解为普通文档形式,以便可以使用$match运算符对它们进行过滤.这样,只返回"匹配"的元素.

"找到"正确做的是匹配符合条件的"文档".由于文档包含匹配的元素,因此返回它们.这两个原则是截然不同的事情.

当你的意思是"过滤"使用聚合.

  • @colymore所以我实际上花了时间复制你的数据并运行给出的最终聚合表达式。编辑已在响应中,整个链按预期工作。所以你没有理由不接受这一点。我已经指出了您原来方法的几个问题,并给出了实际过滤数组的正确解决方案。真正接受给你的建议是很体面的:) (2认同)