Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mongo query for objects with missing key

I have a Mongo db with data stored in this format:

{ "_id" : ObjectId("53e27f602041f3c6fe5373a8"), 
  "miles" : 112650, 
  "history" : [ { "date" : ISODate("2014-05-26T00:00:00Z"), "price" : 8995 }, 
                { "date" : ISODate("2014-06-01T00:00:00Z"), "price" : 8995 } ] }

Objects in the db can have any number "date" and "price data points stored in the history array. However, some of the objects in the db will have multiple history data points but the last "date" key/value pair is not matched with a "price" key/value pair, like this:

{ "_id" : ObjectId("53e27f602041f3c6fe5373a8"), 
  "miles" : 112650, 
  "history" : [ { "date" : ISODate("2014-05-26T00:00:00Z"), "price" : 8995 }, 
                { "date" : ISODate("2014-06-01T00:00:00Z")} ] }

I need to query the db to find 1) all objects where every entry in the history array has a date and a price and 2) all objects where the history array has a "date" entry that is not matched with a "price" entry. Thanks for your help!

like image 588
user3843276 Avatar asked Oct 22 '25 08:10

user3843276


1 Answers

Answering "2" first for reasons that will become clear, what you are basically asking is to find the documents whose array element does contain a "date" value but not a "price". Since there are two conditions for the array element match you want $elemMatch. And to test for the presence of the field you want $exists like so:

db.collection.find({
  "history": {
    "$elemMatch": {
      "date": { "$exists": true },
      "price": { "$exists": false }
    }
  }
})

That returns your second sample since one of the array entries does not have "price".

In order to answer "1", this is basically just the reverse of the logic above, so all you introduce here is the $not operator:

db.collection.find({
  "history": {
    "$not": { 
      "$elemMatch": {
        "date": { "$exists": true },
        "price": { "$exists": false }
      }
    }
  }
})

That produces the first document in the sample as in this case the "price" exists in all elements and therefore the asserted condition would be false but this is turned around by using $not.

like image 106
Neil Lunn Avatar answered Oct 23 '25 23:10

Neil Lunn



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!