简体   繁体   中英

Using MongoDB $split operator on field in object nested in array in aggregation

I have a MongoDB document like this:

{
"_id" : ObjectId("5c949609ff5e3d6119758730"),
"product_name" : "Shoes",
"field_to_split" : "one##two##three##four",
"assets" : [ 
    {
        "url" : "www.blabla.com/1",
        "nested_field_to_split" : "one##two##three##four"
    }, 
    {
        "url" : "www.blabla.com/2",
        "nested_field_to_split" : "one##two##three##four"
    }, 
    {
        "url" : "www.blabla.com/3",
        "nested_field_to_split" : "one##two##three##four"
    }, 
    {
        "url" : "www.blabla.com/4",
        "nested_field_to_split" : "one##two##three##four"
    }
]}

I would like to transform it into this:

{
"_id" : ObjectId("5c949609ff5e3d6119758730"),
"product_name" : "Shoes",
"field_to_split" : "one##two##three##four",
"assets" : [ 
    {
        "url" : "www.blabla.com/1",
        "nested_field_to_split" : ['one', 'two', 'three', 'four']
    }, 
    {
        "url" : "www.blabla.com/2",
        "nested_field_to_split" : ['one', 'two', 'three', 'four']
    }, 
    {
        "url" : "www.blabla.com/3",
        "nested_field_to_split" : ['one', 'two', 'three', 'four']
    }, 
    {
        "url" : "www.blabla.com/4",
        "nested_field_to_split" : ['one', 'two', 'three', 'four']
    }
]}

This has to be done during the aggregation. I was trying to to do this like this:

{  "$project":{
      "assets.nested_field_to_split":{
         "$split":[
            "$assets.nested_field_to_split",
            "##"
         ]
      }
   }
}

I have found in the documentation ( https://docs.mongodb.com/manual/reference/operator/aggregation/project/ ) that "When nesting the fields, you cannot use dot notation inside the embedded document to specify the field, eg contact: { "address.country": <1 or 0 or expression> } is invalid.". So my guess it can't be done. Not like I'm trying at least. I was trying to go around it with a $map or $filter operator but with no success obviously. Please help.

The following query works but might not be the fastest/neatest solution:

db.t.aggregate([
{ $unwind: "$assets" },
{ $project : { "product_name": "$product_name", "field_to_split" :"$field_to_split", "assets_url": "$assets.url", "assets_split" : { $split: ["$assets.nested_field_to_split", "##"] } } },
{ $group : { _id: { _id: "$_id", "product_name": "$product_name", "field_to_split" : "$field_to_split" }, "assets": { $push: { "url": "$assets_url", "nested_field_to_split": "$assets_split" } } } },
{ $project: { _id: "$_id._id", "product_name": "$_id.product_name", "field_to_split" : "$_id.field_to_split", "assets": "$assets" } }
])

Here's the explanation:

  1. $unwind to bring the array out so it can be split
  2. Using $project and $split to split the string
  3. $group to stitch them back together
  4. $project to fix the shape of the document in the desired output

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM