Query date based using milliseconds time on MongoDB - mongodb

I need to search all records that match a date condition. On MongoDB I've a bunch of data like this:
{
"_id" : "9ed3b937-0f43-4613-bd58-cb739a8c5bf6",
"userModels" : {
"5080" : {
"generated_date_timestamp" : NumberLong(1413382499442),
"model_id" : 5080,
},
}
"values" : {}
}
I'm not able to convert that NumberLong in something that can be used by this query:
db.anonProfile.find({
"userModels.5080.generated_date_timestamp" : { "$gte" : ISODate("2013-10-01T00:00:00.000Z") }
});
"_id" has been saved as String so I cannot use for a ObjectID search. [btw, is it possible to do?]
Any clue?
Tnx, Andrea

You can query by
db.anonProfile.find({
"userModels.5080.generated_date_timestamp" : { "$gte" : ISODate("2013-10-01T00:00:00.000Z").getTime() }
});

Related

Updating document with object field

I am new to MongoDB, learning from its documentation but can't find a way to update the document field using MongoDB shell
When I tried to insert the "cancellation" object with either field the query works fine.
db.inventory.update({},
{
$set : { "cancellation":
{
{"date" : new Timestamp()},
{"reason" : "null"}
}
}
},
{upsert : false,multi : true})
It shows
"SyntaxError: invalid property id #(shell)"
on executing this query
Your query is wrong. Try this:
db.inventory.update({},{$set : { "cancellation":
{
"date" : new Timestamp(),
"reason" : "null"
}
} },{upsert : false,multi : true})

querying Date in mongodb with borders included

I'm evaluating the following query on my collection with fake data:
db.test_result.find({"date": {$gte: ISODate("2021-07-27"), $lte: ISODate("2021-08-31")}}).count()
And despite the fact that I use $lte it does not include the second date value. Is it a bug? If so then how do I make the query so that the left and right borders are included?
Here is what a fake json obj looks like:
{
"nfl": "Some",
"rStatus": false,
"mac": "02:00:00:00:00:00",
"date": "2021-07-27T12:17:57",
"MDCode": "123132132123",
}
With this given input:
{
"_id" : ObjectId("596c6fea53cc7100104628fa"),
"timestamp" : ISODate("2017-07-17T08:06:02.041Z"),
}
{
"_id" : ObjectId("596c7162973f33000fc8bb81"),
"timestamp" : ISODate("2017-07-17T08:12:18.170Z")
}
{
"_id" : ObjectId("596c736c15371f00106b9e3a"),
"timestamp" : ISODate("2017-07-17T08:21:00.291Z")
}
This query:
...find({"timestamp": {$gte: ISODate("2017-07-17T08:06:02.041Z"), $lte: ISODate("2017-07-17T08:12:18.170Z")}})
Would return:
{
"_id" : ObjectId("596c6fea53cc7100104628fa")
"timestamp" : ISODate("2017-07-17T08:06:02.041Z")
}
{
"_id" : ObjectId("596c7162973f33000fc8bb81"),
"timestamp" : ISODate("2017-07-17T08:12:18.170Z")
}
Which is what you would expect, the results match to the dot the 2 borders. So in a nutshell it would be included if it is an exact match, otherwise you would get only the once in between.

MONGODB - cast type of every object in array of objects

I have MongoDB Collection where some documents have arrays of objects. One of the fields of this objects is timestamp.
The problem is that historically some of timestamp values are Strings (e.g. '2018-02-25T13:33:56.675000') or Date and some of them are Double (e.g. 1528108521726.26).
I have to convert all of them to Double.
I've built the query to get all the documents with the problematic type:
db.getCollection('Cases').find({sent_messages: {$elemMatch:{timestamp: {$type:[2, 9]}}}})
And I also know how to convert Date-string to double using JS:
new Date("2018-02-18T06:39:20.797Z").getTime()
> 1518935960797
But I can't build the proper query to perform the update.
Here is an example of such a document:
{
"_id" : ObjectId("6c88f656532aab00050dc023"),
"created_at" : ISODate("2018-05-18T03:43:18.986Z"),
"updated_at" : ISODate("2018-05-18T06:39:20.798Z"),
"sent_messages" : [
{
"timestamp" : ISODate("2018-02-18T06:39:20.797Z"),
"text" : "Hey",
"sender" : "me"
}
],
"status" : 1
}
After the update it should be:
{
"_id" : ObjectId("6c88f656532aab00050dc023"),
"created_at" : ISODate("2018-05-18T03:43:18.986Z"),
"updated_at" : ISODate("2018-05-18T06:39:20.798Z"),
"sent_messages" : [
{
"timestamp" : 1518935960797.00,
"text" : "Hey",
"sender" : "me"
}
],
"status" : 1
}
As per your question, you are trying to fetch the record first.
db.getCollection('Cases').find({sent_messages: {$elemMatch:{timestamp: {$type:[2, 9]}}}})
Then convert date in JS:
new Date("2018-02-18T06:39:20.797Z").getTime()
And then this is an update query:
db.getCollection('Cases').updateOne({_id:ObjectId("6c88f656532aab00050dc023")}, { $set: { "sent_messages.$.timestamp" : "218392712937.0" }})
And if you want to update all records then you should write some forEach mechanism. I think you have already this implemented.
Hope this may help you.
Finally I just do it with JS code that can be run in mongo console:
db.getCollection('Cases').find({sent_messages: {$elemMatch:{timestamp: {$type:[2, 9]}}}}).forEach(function(doc) {
print('=================');
print(JSON.stringify(doc));
doc.sent_messages.forEach(function(msg){
var dbl = new Date(msg.timestamp).getTime();
print(dbl);
msg.timestamp = dbl;
});
print(JSON.stringify(doc))
db.Cases.save(doc);
} )
Thanks all for your help!

Optimizing query with &elemMatch inside array

First of all I'd to apologize for my english.
I have serious issue with performance on my query. Unfortunetly I'm pretty new to mongoDB. So i have collection test which looks similar to this
{
"_id" : ObjectId("1"),
[...]
"statusHistories" : [
{
"created" : ISODate("2016-03-15T14:59:11.597Z"),
"status" : "STAT1",
},
{
"created" : ISODate("2016-03-15T14:59:20.465Z"),
"status" : "STAT2",
},
{
"created" : ISODate("2016-03-15T14:51:11.000Z"),
"status" : "STAT3",
}
],
}
statusHistories is an array.
Daily there's more than 3000 records inserted into that collection.
What I want to achieve is to find all tests that have given status and they are beeten two dates. So I have prepared query like this:
db.getCollection('test').find({
'statusHistories' : {
$elemMatch : {
created : {
"$gte" : ISODate("2016-07-11 00:00:00.052Z"),
"$lte" : ISODate("2016-07-11 23:59:00.052Z")
},
'status' : 'STAT1'
}
}
})
It gives expected result. Unfortunetly it takes around 120 seconds to complete. Which is way too long. Surprisingly if I split this query into two seperate it takes way less:
db.getCollection('test').find({
'statusHistories' : {
$elemMatch : {
created : {
"$gte" : ISODate("2016-07-11 00:00:00.052Z"),
"$lte" : ISODate("2016-07-11 23:59:00.052Z")
}
}
}
})
db.getCollection('test').find({
'statusHistories' : {
$elemMatch : {
'status' : 'STAT1'
}
}
})
Both of them need less then a second in order to complete.
So what am I doing wrong with my original query? I need to take those records in one query but when I combine two elemMatch statements into one it takes ages. I tried to ensureIndex on statusHistories but it didn't work out. Any suggestion would be really helpfull.

substract two date end return value

I need help to build a query to substract two dates in mongodb.
I have some documents like above :
{"_id" : "32472034809", "center": "102030", dateArq : 141010, inDate : "ISODate("2014-06-06T02:57:19.000-03:00)", biDate : ISODate("2014-06-07T02:57:19.000-03:00)"}
And Im trying to write a query
db.teste.aggregation([{$match : {dateArq : 141010}},{$project : {$subtract : ["$biDate" "$inDate"]}}])
In fact, I want to do : for each _id I want to result biDate - inDate , because I need to see if dateArq keep in a line constante.
In Oracle I did
select dateArq, (biDate - inDate) diff from teste where dateArq = 141010
Tks for help
The document and aggregation pipeline provided had syntax problems, and you needed to put a field name for the result of the $subtract, but otherwise your pipeline works for me:
> db.test.findOne()
{
"_id" : "32472034809",
"center" : "102030",
"dateArq" : 141010,
"inDate" : ISODate("2014-06-06T05:57:19Z"),
"biDate" : ISODate("2014-06-07T05:57:19Z")
}
> db.test.findOnedb.test.aggregate([
{ "$match" : { "dateArq" : 141010 } },
{ "$project" : { "dateDiff" : { "$subtract" : ["$biDate", "$inDate"] } } }
])
{ "_id" : "32472034809", "dateDiff" : NumberLong(86400000) }