How yo query a string with an ObjectID in subquery - python

I have a query problem in mongoDB.
This query executed :
db.client_data.find(    
... {       
... client_data_type_id : ObjectId("533bde998a223858e3c8d352"),  "list_attributes.535e70158a22382679a738d3" : "535f5b798a22383f5a59c86f"    
... },    
... {
... _id : 1   
... } )
gives me this result
{ "_id" : ObjectId("535f5bb78a22383f5a59c870") }
{ "_id" : ObjectId("535f5bd28a22383f5a59c871") }
{ "_id" : ObjectId("535f5bda8a22383f5a59c872") }
I now want to execute this query :
db.client_data.find(
{
     client_data_type_id : ObjectId("533a7d258a22383070aa1092"),
     "list_attributes.535e27768a22387ca86974cb" :
     {
$in : [
db.client_data.find(    
{       
client_data_type_id : ObjectId("533bde998a223858e3c8d352"),  "list_attributes.535e70158a22382679a738d3" : "535f5b798a22383f5a59c86f"    
},    
{
_id : 1   
} )
]
    }
  },
  {
          _id : 0,
list_attributes : 1
  }
)
If i execute this query with string, it works :
db.client_data.find(
  {
      client_data_type_id : ObjectId("533a7d258a22383070aa1092"),
"list_attributes.535e27768a22387ca86974cb" :
{
$in : [
"535f5bda8a22383f5a59c872",
"535f5bd28a22383f5a59c871",
"535f5bb78a22383f5a59c870",
]
}
  },
  {
          _id : 0,
list_attributes : 1
  }
)
This gives me the right result.
But with the subquery, it doesn't work because the subquery gives me ObjectID and I have to execute query with String.
Do you know how to do this ??
Thanks a lot!

You can use str(objectid) to turn an ObjectId into it's hexadecimal representation.
http://api.mongodb.org/python/1.7/api/pymongo/objectid.html

Related

MongoDB TTL index doesn't delete expired documents

I'm trying to create a collection named ttl, and using a TTL index, make the documents in that collection expire after 30 seconds.
I've created the collection using mongoengine, like so:
class Ttl(Document):
meta = {
'indexes': [
{
'name': 'TTL_index',
'fields': ['expire_at'],
'expireAfterSeconds': 0
}
]
}
expire_at = DateTimeField()
The index has been created and Robo3T shows it's as expected.
The actual documents are inserted to the collection using mongoengine as well:
current_ttl = models.monkey.Ttl(expire_at=datetime.now() + timedelta(seconds=30))
current_ttl.save()
The save is successful (the document is inserted into the DB), but it never expires!
How can I make the documents expire?
I'm adding the collection's contents here as well in case I'm saving them wrong. These are the results of running db.getCollection('ttl').find({}):
/* 1 */
{
"_id" : ObjectId("5ccf0f5a4bdc6edcd3773cd6"),
"created_at" : ISODate("2019-05-05T19:31:10.715Z")
}
/* 2 */
{
"_id" : ObjectId("5ccf121c0b792dae8f55cc80"),
"expire_at" : ISODate("2019-05-05T19:41:08.220Z")
}
/* 3 */
{
"_id" : ObjectId("5ccf127d6729084a24772fad"),
"expire_at" : ISODate("2019-05-05T19:42:47.522Z")
}
/* 4 */
{
"_id" : ObjectId("5ccf15bab124a97322da28de"),
"expire_at" : ISODate("2019-05-05T19:56:56.359Z")
}
The indexes themselves, as per the results of db.getCollection('ttl').getIndexes(), are:
/* 1 */
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "monkeyisland.ttl"
},
{
"v" : 2,
"key" : {
"expire_at" : 1
},
"name" : "TTL_index",
"ns" : "monkeyisland.ttl",
"background" : false,
"expireAfterSeconds" : 0
}
]
My db.version() is 4.0.8 and it's running on Ubuntu 18.04.
The issue is with:
current_ttl = models.monkey.Ttl(expire_at=datetime.now() + timedelta(seconds=30))
that should be
current_ttl = models.monkey.Ttl(expire_at=datetime.utcnow() + timedelta(seconds=30))

Pymongo $in + aggregate with regex not working in pymongo

I am running the following query in Mongo shell :
db.coll.aggregate([ { "$match" : { "_id":{"$in" : [/^4_.*/,/^3_.*/]}}},
{ "$unwind" : "$rp"},
{"$group":{"_id": "$_id", "rp": { "$push": "$rp" }}} , {"$limit":120}],{allowDiskUse:true})
which is working correctly. But when I am trying the same in pymongo as :
ids_list = [3,4]
ids_list = ["^" + str(c_id) + "_.*" for c_id in ids_list]
pipe = [ { "$match" : { "_id":{"$in" : ids_list}}},
{ "$unwind" : "$rp"},
{"$group":{"_id": "$_id", "rp": { "$push": "$rp" }}} , {"$limit":500}]
res = list(db.coll.aggregate(pipeline = pipe,allowDiskUse=True))
which is not working. I am new to Mongo queries.
I changed the for loop where each element is compiled using re module i.e.
ids_list = [re.compile("^" + str(c_id) + "_.*") for c_id in ids_list]
and it worked :)

MongoDB pipeline unwind and check for empty array

I'm unwinding one field which is an array of date objects, however in some cases there are empty array's which is fine. I'd like the same treatment using a pipeline, but in some cases, I want to filter the results which have an empty array.
pipeline = []
pipeline.append({"$unwind": "$date_object"})
pipeline.append({"$sort": {"date_object" : 1}})
I want to use the pipeline format, however the following code does not return any records:
pipeline.append({"$match": {"date_object": {'$exists': False }}})
nor does the following work:
pipeline.append({"$match": {"date_object": []}})
and then:
results = mongo.db.xxxx.aggregate(pipeline)
I'm also trying:
pipeline.append({ "$cond" : [ { "$eq" : [ "$date_object", [] ] }, [ { '$value' : 0 } ], '$date_object' ] } )
But with this I get the following error:
.$cmd failed: exception: Unrecognized pipeline stage name: '$cond'
However if I query using find such as find({"date_object": []}), I can get these results. How can I make this work with the pipeline.
I've done in MongoDB shell, but it can be translated into Python easily in python language.
Is it your requirements?
I suppose you have such structure:
db.collection.save({foo:1, date_object:[new Date(), new Date(2016,1,01,1,0,0,0)]})
db.collection.save({foo:2, date_object:[new Date(2016,0,16,1,0,0,0),new Date(2016,0,5,1,0,0,0)]})
db.collection.save({foo:3, date_object:[]})
db.collection.save({foo:4, date_object:[new Date(2016,1,05,1,0,0,0), new Date(2016,1,06,1,0,0,0)]})
db.collection.save({foo:5, date_object:[]})
// Get empty arrays after unwind
db.collection.aggregate([
{$project:{_id:"$_id", foo:"$foo",
date_object:{
$cond: [ {"$eq": [{ $size:"$date_object" }, 0]}, [null], "$date_object" ]
}
}
},
{$unwind:"$date_object"},
{$match:{"date_object":null}}
])
// Get empty arrays before unwind
db.collection.aggregate([
{$match:{"date_object.1":{$exists:false}}},
{$project:{_id:"$_id", foo:"$foo",
date_object:{
$cond: [ {"$eq": [{ $size:"$date_object" }, 0]}, [null], "$date_object" ]
}
}
},
{$unwind:"$date_object"}
])
Only empty date_object
[
{
"_id" : ObjectId("56eb0bd618d4d09d4b51087a"),
"foo" : 3,
"date_object" : null
},
{
"_id" : ObjectId("56eb0bd618d4d09d4b51087c"),
"foo" : 5,
"date_object" : null
}
]
At the end, if you need only empty date_object, you don't need to aggregate, you can easely achieve it with find:
db.collection.find({"date_object.1":{$exists:false}},{date_object:0})
Output
{
"_id" : ObjectId("56eb0bd618d4d09d4b51087a"),
"foo" : 3
}
{
"_id" : ObjectId("56eb0bd618d4d09d4b51087c"),
"foo" : 5
}

MongoDB Query does not return expected results

I'm using Python. I send datetime.utcnow() to my MongoDB.
What is wrong with my code:
deltaTime = timedelta(minutes=1)
s.find({"status" : "pending",
"$and" : [{"time" : {"$lt" : datetime.utcnow()}},
{"time" : {"$gt" : datetime.utcnow() - deltaTime }}
]
}, page=0 , perpage=15 )
but it doesn't work.
and the same query in MongoDb does not work either:
db.s.find(
{"status" : "pending" ,
"$and" :
[
{"time" : {"$lt" : ISODate("2014-06-05 06:59:31.442Z") } }
,
{"time" : {"$gt" : ISODate("2014-06-05 05:59:31.442Z") } }
]
}
)
MongoDB says "Script executed successfully but there is no result to show"
I have records in between! but there is no result, I also have tried the MongoDB query without ISODate() and still there is no result!
I've solved this issue by the following query:
db.s.find(
{
"status" : "Pending"
,
"time" : {
"$gt" : ISODate("2014-06-05 06:01:29.397069") ,
"$lt" : ISODate("2014-06-05 07:01:29.397069")
}
}
)
and the "$and" have not worked for me in this case.

Pymongo dict element in array output

I got a database with this info:
{"_id":1, "test":6,"foo":[{"mom":5,"dad":10},{"mom":7, "dad":12}]}
{"_id":2, "test":9,"foo":[{"mom":6,"dad":20},{"mom":7, "dad":15}]}
{"_id":3, "test":10, "foo":[{"mom":10,"dad":13},{"mom":2, "dad":19}]}
and i query in mongo from db with mom=7:
cursor = foo.find({"foo.mom":7},{"foo.$":1,"_id":0, "test":1})
for key in cursor:
print key
it prints me this:
{"test":6,"foo":[{"mom":7, "dad":12}]}
{"test":9,"foo":[{"mom":7, "dad":15}]}
if i use
print key['test']
i'll get the result of only "test"
So, the question is: how can i get the result like this:
{"test":6,"foo":[{"dad":12}]}
{"test":9,"foo":[{"dad":15}]}
i tried to use
print key["foo.dad"]
but it only returns an error
As the value of "foo" is saved in an array, you need to use key['foo'][0]['dad'] to print the value of 'dad' from the result.
The code I used is like this:
cursor = foo.find({"foo.mom":7},{"foo.$":1,"_id":0, "test":1})
for key in cursor:
print key
print key['test']
print key['foo'][0]['dad']
And the result I got is like this:
{u'test': 6.0, u'foo': [{u'dad': 12.0, u'mom': 7.0}]}
6.0
12.0
{u'test': 9.0, u'foo': [{u'dad': 15.0, u'mom': 7.0}]}
9.0
15.0
If you want to get the result without the 'mom' field:
{"test":6,"foo":[{"dad":12}]}
{"test":9,"foo":[{"dad":15}]}
you can use the aggregation framework:
db.foo.aggregate([
{ $unwind : "$foo" },
{ $match : { "foo.mom" : 7 }},
{ $project : {
_id : 0,
test : 1,
"foo.dad" : "$foo.dad"
}},
])
And the result is:
{
"result" : [
{
"test" : 6,
"foo" : {
"dad" : 12
}
},
{
"test" : 9,
"foo" : {
"dad" : 15
}
}
],
"ok" : 1
}

Categories

Resources