Search code examples
node.jsmongodbsails.js

How to fetch particular array elements from object's array in mongo db


I've a row, which contains data like:

{
    "_id" : ObjectId("5bcef76b0c9a4c194cf6d0a7"),
    "userid" : ObjectId("5bc5ae4355418805b8caabb3"),
    "transactionid" : "ch_1DON67EzCa9AoDtY51kialzs",
    "adminid" : [
        "5b5af339bc69c511816e8a2f",
        "5b87948d97b752099c086708"
    ],
    "amount" : 3220,
    "ispaid" : true,
    "products" : [
        {
            "productid" : ObjectId("5bceba35003c87043997a1d4"),
            "quantity" : 2,
            "price" : 200,
            "type" : "product",
            "isCanceled" : false,
            "isDeliverd" : false,
            "createdby" : "schooladmin",
            "userid" : ObjectId("5b87948d97b752099c086708"),
            "isReadyToPickup" : false,
            "name" : "The Second Product",
            "description" : "                "
        },
        {
            "productid" : ObjectId("5bc5b2df55418805b8caabbd"),
            "quantity" : 2,
            "price" : 100,
            "type" : "product",
            "isCanceled" : false,
            "isDeliverd" : false,
            "createdby" : "superadmin",
            "userid" : ObjectId("5b5af339bc69c511816e8a2f")
        },
        {
            "productid" : ObjectId("5bc5bc5fe84c3d028aaa269c"),
            "quantity" : 2,
            "price" : 100,
            "type" : "product",
            "isCanceled" : false,
            "isDeliverd" : false,
            "createdby" : "superadmin",
            "userid" : ObjectId("5b5af339bc69c511816e8a2f")
        }
],
    "paymentUsing" : "card",
    "cardBrand" : "Visa",
    "country" : "US",
    "paymentDate" : "2018-10-23T10:26:51.856Z"
}

I want to perform search on products object's all element. And if any of them match, that entire object will be store in array variable.

Suppose, I try to search The Second Product string from name object of products array. then it would be give me the all element. like

[
    {
        "productid" : ObjectId("5bceba35003c87043997a1d4"),
        "quantity" : 2,
        "price" : 200,
        "type" : "product",
        "isCanceled" : false,
        "isDeliverd" : false,
        "createdby" : "schooladmin",
        "userid" : ObjectId("5b87948d97b752099c086708"),
        "isReadyToPickup" : false,
        "name" : "The Second Product",
        "description" : "                "
    } 
]

And if two or more elements founds then it will return it array accordingly.

Please suggest me the solution. Thank You in Advance. :)


Solution

  • Using aggregation pipeline we can get the desired result.

    Approach 1:

    A simpler approach if we don't have nested arrays

    $filter is used within $project to get the desired result

    db.collection_name.aggregate([
      {
        $project: {
          products: {
            $filter: {
              input: "$products",
              as: "product",
              cond: {
                $eq: [
                  "$$product.name",
                  "The Second Product"
                ]
              }
            }
          }
        }
      }
    ])
    

    Approach 2:

    $unwind to unwind the products array

    $match to retrieve the matching documents

    $project to project only the required output elements

    db.collection_name.aggregate([
     { $unwind: "$products" },
     { $match:{"products.name":"The Second Product"} }, 
     { $project:{products:1}} 
    ])
    

    Output of the above queries(Approach 1 or Approach 2)

    {
            "_id" : ObjectId("5bcef76b0c9a4c194cf6d0a7"),
            "products" : {
                    "productid" : ObjectId("5bceba35003c87043997a1d4"),
                    "quantity" : 2,
                    "price" : 200,
                    "type" : "product",
                    "isCanceled" : false,
                    "isDeliverd" : false,
                    "createdby" : "schooladmin",
                    "userid" : ObjectId("5b87948d97b752099c086708"),
                    "isReadyToPickup" : false,
                    "name" : "The Second Product",
                    "description" : "                "
            }
    }