Question

Listed are the following sample documents in a test collection

My requirement is to extract *only" two fields "host.name" and "host.config.storageDevice.scsiLun.lunType" matching the condition that "host.config.storageDevice.scsiLun.lunType" : "cdrom1" and "host.name" : "on-xxx"

Like I mentioned above , I only want attribute "lunType" to be displayed in the array and not "a" or "b"

I attempted to use both $elemMatch and $projection and it always seems to return all the attributes of array "lunType" ... Am I missing anything here

Attempted in reference to documentation http://docs.mongodb.org/manual/reference/projection/elemMatch/

Query

db.test.find({"host.config.storageDevice.scsiLun": { $elemMatch: { "lunType" : "cdrom1" } } },{ "host.name" : 1, "host.config.storageDevice.scsiLun.$" : 1})

db.test.find({"host.config.storageDevice.scsiLun.lunType" : "cdrom1" },{ "host.name" : 1, "host.config.storageDevice.scsiLun.$" : 1})

Documents in collection

    {
    "_id" : ObjectId("51d57f3ad4ebc6c87962d4c0"),
    "host" : {
    "name" : "on-xxx",
    "config" : {
        "storageDevice" : {
            "scsiLun" : [ 
                {
                    "a" : "1",
                    "lunType" : "cdrom1"
                }, 
                {
                    "a" : "2",
                    "lunType" : "disk2"
                }, 
                {
                    "a" : "3",
                    "lunType" : "disk3"
                }
            ]
        }
        }
    }
    }
    , 
    {
    "_id" : ObjectId("51d57f59d4ebc6c87962d4c1"),
    "host" : {
    "name" : "on-yyy",
    "config" : {
        "storageDevice" : {
            "scsiLun" : [ 
                {
                    "a" : "4",
                    "lunType" : "cdrom4"
                }, 
                {
                    "a" : "5",
                    "lunType" : "disk5"
                }, 
                {
                    "a" : "6",
                    "lunType" : "disk6"
                }
            ]
        }
       }
    }
    }
    , 
    {
    "_id" : ObjectId("51d57f74d4ebc6c87962d4c2"),
    "host" : {
    "name" : "on-zzz",
    "config" : {
        "storageDevice" : {
            "scsiLun" : [ 
                {
                    "a" : "7",
                    "lunType" : "cdrom11"
                }, 
                {
                    "a" : "8",
                    "lunType" : "disk22"
                }, 
                {
                    "a" : "9",
                    "lunType" : "disk32"
                }
            ]
        }
    }
    }
    }
Was it helpful?

Solution

All $elemMatch does is to return the first element of the array that matches a criteria, but it will give you the entire element, that is both "a" and "lunType" properties.

What might get the desired result with aggregation using $unwind to break down the array, then $match to filter and $project to show only the "lunType" field.

I didn't test the query but it should look like this:

    db.test.aggregate(
        { $unwind : "$host.config.storageDevice.scsiLun" },
        { $match : { host.name : "on-xxx" , 
             host.config.storageDevice.scsiLun.lunType : "cdrom1" } },
        { $project : {
            _id : 0 ,
            host.config.storageDevice.scsiLun.lunType : 1 }
    );
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top