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
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))
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 :)
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
}
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.
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
}