MongoDB query for variable key data

This is how the objects are stored in the collection.

{
	"_id":{
		"$oid": "60eaa0e2126e154cf079067f"
	},
	"data": {
		"1625989346292":{
			"temp": 23.3,
			"humid": 0.75
		
		},
		"1625989346293":{
			"temp": 30.5
		},
		"1625989346294":{
			"humid": 0.85
		},
		"1625989346295":{
			"temp": 28.3,
			"humid": 0.65
		}
	}
}

If I want the time instance(s) (parent key for “temp” and “humid”) when the temperature is 30.5, what would the MongoDB query look like?

Please Note: We do not know the time instance and there are no two identical time-stamp keys, hence date.<date object>.temp would not work.

You can write a query for this but it cannot use an index so it won’t be efficient on a large collection. If you combine it without another query predicate that index could be used though. The way you do it is via $expr which lets you use aggregation expressions.

 db.coll.find({$expr:{$lt:[0, {$size:{$filter:{input:{$objectToArray:"$data"},cond:{$eq:["$$this.v.temp",30.5]}}}}]}})

This returns all documents which match condition that some value of temp inside some field inside data is equal to 30.5 - if you want to get back not the full document but just the subdocument corresponding to that temp value, you also need a projection:

 db.coll.find(
     {$expr:{$lt:[0, {$size:{$filter:{input:{$objectToArray:"$data"},cond:{$eq:["$$this.v.temp",30.5]}}}}]}},
     {data:{$arrayToObject:{$filter:{input:{$objectToArray:"$data"},cond:{$eq:["$$this.v.temp",30.5]}}}}}
  )

Which given your sample document will return

  { "_id" : ObjectId("60eaa0e2126e154cf079067f"), "data" : { "1625989346293" : { "temp" : 30.5 } } }

Asya
P.S. if there is more than one, you’ll get all of them

2 Likes

Thank you for your answer @Asya_Kamsky.

We can just use this query right?
db.collection.find({}, {data:{$arrayToObject:{$filter:{input:{$objectToArray:"$data"},cond:{$eq:["$$this.v.temp",30.5]}}}}}
)

Well, having {} as the query predicate means you will examine and return every single document in the collection and then end up returning empty data object for documents that didn’t have any elements which had the temperature you’re interested in.

Ah okay. When I tried it with the query predicate on my node.js environment, I get the following error:
UnhandledPromiseRejectionWarning: MongoError: empty variable names are not allowed

Are you sure you didn’t have a typo? I tested this before pasting it in. Maybe show the exact query you run with exact error?

I am pretty sure that it’s not a typo. The same query works on Mongo Playground, and not on my node.js environment.

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