2

I have a document like this..

{
    "_id" : ObjectId("59b0ea9b3a91af574a3e0464"),
    "machineID" : "b83c",
    "sensorState" : [ 
        {
            "data" : "377",
            "sensor" : "solar",
            "time" : ISODate("2017-09-20T19:42:58.766Z")
        }, 
        {
            "data" : "35",
            "sensor" : "photosynthetic",
            "time" : ISODate("2017-09-20T19:42:58.782Z")
        }, 
        {
            "data" : "370",
            "sensor" : "solar",
            "time" : ISODate("2017-09-20T19:43:29.089Z")
        }, 
        {
            "data" : "400",
            "sensor" : "solar",
            "time" : ISODate("2017-09-20T19:44:29.089Z")
        }, 
        {
            "data" : "35",
            "sensor" : "photosynthetic",
            "time" : ISODate("2017-09-20T19:43:29.110Z")
        }
    ]
}

I want to retrieve only those sub documents in the sensorState array which match sensor=solar. So, I tried to do like this:

db.getCollection('sensorDB').find({ },
    { "sensorState" : { $elemMatch: {data : "35" } } })

But it shows only one result:

{
    "_id" : ObjectId("59b0ea9b3a91af574a3e0464"),
    "sensorState" : [ 
        {
            "data" : "35",
            "sensor" : "photosynthetic",
            "time" : ISODate("2017-09-20T19:42:58.782Z")
        }
    ]
}

However, I want to find all sub documents in the sensorState array which match sensor=solar. It looks like $elemMatch just can select one result.

1
  • db.getCollection('sensorDB').find({'sensorState.data':"35",'sensorState.sensor':"solar"}). Just try this Commented Oct 3, 2017 at 12:08

2 Answers 2

3

I found answer myself. use aggregate the answer is like this

db.getCollection('sensorDB').aggregate(
        {$match: {machineID:"b83c"}},
        {$unwind:"$sensorState"},
        {$match: {"sensorState.sensor":"solar"}}
)
Sign up to request clarification or add additional context in comments.

Comments

1

You are attempting to project with elemMatch but according to the docs

The $elemMatch operator limits the contents of an field from the query results to contain only the first element matching the $elemMatch condition.

So, the behaviour you are seeing is the expected behaviour for elemMatch-in-a-projection.

You can get use $project and $filter in an aggregation pipeline to get your end result.

Given the sample document included in your OP the following command ...

db.getCollection('elemMatch').aggregate([
  // projects on the sensorState sub documents and filters the output to only return sub 
  // documents having data=35
  {$project: {
      sensorState: {
        $filter: {
            input: "$sensorState",
            as: "sensorState",
            cond: { $eq: [ "$$sensorState.data", '35' ] }
          }
        }
      }
  }
])

... will return:

{
    "_id" : ObjectId("59b0ea9b3a91af574a3e0464"),
    "sensorState" : [ 
        {
            "data" : "35",
            "sensor" : "photosynthetic",
            "time" : ISODate("2017-09-20T19:42:58.782Z")
        }, 
        {
            "data" : "35",
            "sensor" : "photosynthetic",
            "time" : ISODate("2017-09-20T19:43:29.110Z")
        }
    ]
}

Your questions shows an attempted match on data=35 but it also states:

I want to find all sensorState.sensor = solar

So, here's the above command with that condition:

db.getCollection('elemMatch').aggregate([
  // projects on the sensorState sub documents and filters the output to only return sub 
  // documents having sensor=solar
  {$project: {
      sensorState: {
        $filter: {
            input: "$sensorState",
            as: "sensorState",
            cond: { $eq: [ "$$sensorState.sensor", 'solar' ] }
          }
        }
      }
  }
])

Which returns:

{
    "_id" : ObjectId("59b0ea9b3a91af574a3e0464"),
    "sensorState" : [ 
        {
            "data" : "377",
            "sensor" : "solar",
            "time" : ISODate("2017-09-20T19:42:58.766Z")
        }, 
        {
            "data" : "370",
            "sensor" : "solar",
            "time" : ISODate("2017-09-20T19:43:29.089Z")
        }, 
        {
            "data" : "400",
            "sensor" : "solar",
            "time" : ISODate("2017-09-20T19:44:29.089Z")
        }
    ]
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.