Find or aggregate in this type of query

Hello guys
My collection consist of nested documents.I have a query that look like this:

mydb1.mongodbbucketright.find(
    {"samples.timestamp1": {"$gte": datetime.strptime("2010-01-01 00:05:00", "%Y-%m-%d %H:%M:%S"),
                               "$lte": datetime.strptime("2015-01-01 00:05:00", "%Y-%m-%d %H:%M:%S")},
     "samples.id13":{"$gt":5}},

    {"samples.$": 1 })

Is position projection going to help here?
Sometimes it seems that i get less results than expected
So i changed the query and now it look like this:

mydb1.mongodbbucketright.aggregate([

    {
        "$match": {
            "samples.timestamp1": {"$gte": datetime.strptime("2010-01-01 00:05:00", "%Y-%m-%d %H:%M:%S"),
                          "$lte" :datetime.strptime("2015-01-01 00:05:00", "%Y-%m-%d %H:%M:%S")},
            "samples.id13": {"$gt": 5}
        }
    },
    { "$unwind": "$samples" },
    {
        "$match": {
            "samples.timestamp1": {"$gte": datetime.strptime("2010-01-01 00:05:00", "%Y-%m-%d %H:%M:%S"),
                      "$lte": datetime.strptime("2015-01-01 00:05:00", "%Y-%m-%d %H:%M:%S")},
            "samples.id13": {"$gt": 5}
        }
    },


])

I want the query to be optimized
What is your opinion in that?
Did i choose the right option?
Using mongodb with pymongo

Thanks in advance

The problem with your first version with positional projection is that it’s ambiguous. Since samples is an array, what if different elements match the two clauses in the query predicate? Which element do you want returned by that projection?

If you don’t intend for the condition to be satisfied by two different elements, you must use $elemMatch in your query. Certainly that’s what the aggregation syntax is doing - after unwind it will only match original elements that match both conditions. Change your original find and it’s going to return only the correct results you want:

    {"samples":{"$elemMatch":{
         "timestamp1": {
                      "$gte": datetime.strptime("2010-01-01 00:05:00", "%Y-%m-%d %H:%M:%S"),
                      "$lte": datetime.strptime("2015-01-01 00:05:00", "%Y-%m-%d %H:%M:%S")
         },
         "id13":{"$gt":5}
    }}}

Asya

1 Like

Thank you @Asya_Kamsky yes the elemMatch seems to be way faster than the aggregation .I have one thing more to ask.Can i use elemMatch in an pipeline like this:

mydb1.mongodbbucketnocpu3index.aggregate(
  [
      {
          "$match": {
              "samples.timestamp1": {"$gte": datetime.strptime("2019-01-01 00:00:00", "%Y-%m-%d %H:%M:%S"),
                        "$lte": datetime.strptime("2020-12-31 01:55:00", "%Y-%m-%d %H:%M:%S")},

          }
      },
{ "$unwind": "$samples" },
      {
          "$group": {

              "_id": {"$dateToString": {"format": "%Y-%m-%d %H", "date": "$samples.timestamp1"}},
              "max_id13": {
                  "$max": "$samples.id13"
              }
          }
      },

      {
          "$project": {
              "_id": 0,
              "day": "$_id",
              "max_id13": 1
          }
      },
     {"$sort": {"day": -1}},
     { "$limit": 5}
    ]
)

Instead of match?Will ElemMatch be better?Can we use elemMatch on an aggregate like this?

I’m not sure I understand the question - I don’t see $elemMatch in the code you posted…

Hi @Asya_Kamsky.There is something i camt understand.what is the difference between elemmatch projection and elem query.i used find with elemmatch,is this elemmatch query or elemmatch projection i can’t understand

Elemmatch returns only the first subdocument that agrees with the condition?

In a query, $elemMatch will indicate entire document should be matched if any array element matches a particular condition.

In a projection, $elemMatch indicates the first matching element of an array should be the only array element projected.

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.