Find documents 7 days apart in mongodb - mongodb

Suppose, we have this type of documents :
{
"_id" : ObjectId("4c02c58de500fe1be1000305"),
"date" : ""20090530"
}
{
"_id" : ObjectId("4c02c58de500fe1be1000005"),
"date" : ""20090607"
}
Is it possible to find/group all documents with 7 days between them?
With aggregate?

You can write something like this, I believe you won't be needing aggregation here, if you are doing this for the same collection:
db.collectionName.find({date: { $gte: "20090530", $lte: "20090607" } } );
Reference: $lte and $gte

Related

MongoDB 4.0 aggregation addFields not saving documents after using toDate

I have the following documents,
{
"_id" : ObjectId("5b85312981c1634f59751604"),
"date" : "0"
},
{
"_id" : ObjectId("5b85312981c1634f59751604"),
"date" : "20180330"
},
{
"_id" : ObjectId("5b85312981c1634f59751604"),
"date" : "20180402"
},
{
"_id" : ObjectId("5b85312981c1634f59751604"),
"date" : "20180323"
},
I tried to convert date to ISODate using $toDate in aggregation,
db.documents.aggregate( [ { "$addFields": { "received_date": { "$cond": [ {"$ne": ["$date", "0"] }, {"$toDate": "$date"}, new Date("1970-01-01") ] } } } ] )
the query executed fine, but when I
db.documents.find({})
to examine all the documents, nothing changed, I am wondering how to fix it. I am using MongoDB 4.0.6 on Linux Mint 19.1 X64.
As they mentioned in the comments, aggregate doesn't update documents in the database directly (just an output of them).
If you'd like to permanently add a new field to documents via aggregation (aka update the documents in the database), use the following .forEach/.updateOne method:
Your example:
db.documents
.aggregate([{"$addFields":{"received_date":{"$cond":[{"$ne":["$date","0"]}, {"$toDate": "$date"}, new Date("1970-01-01")]}}}])
.forEach(function (x){db.documents.updateOne({_id: x._id}, {$set: {"received_date": x.received_date}})})
Since _id's value is an ObjectID(), there may be a slight modification you need to do to {_id:x._id}. If there is, let me know and I'll update it!
Another example:
db.users.find().pretty()
{ "_id" : ObjectId("5acb81b53306361018814849"), "name" : "A", "age" : 1 }
{ "_id" : ObjectId("5acb81b5330636101881484a"), "name" : "B", "age" : 2 }
{ "_id" : ObjectId("5acb81b5330636101881484b"), "name" : "C", "age" : 3 }
db.users
.aggregate([{$addFields:{totalAge:{$sum:"$age"}}}])
.forEach(function (x){db.users.updateOne({name: x.name}, {$set: {totalAge: x.totalAge}})})
Being able to update collections via the aggregation pipeline seems to be quite valuable because of what you have the power to do with aggregation (e.g. what you did in your question, doing calculations based on other fields within the document, etc.). I'm newer to MongoDB so maybe updating collections via aggregation pipeline is "bad practice", but it works and it's been quite valuable for me. I wonder why it isn't more straight-forward to do?
Note: I came up with this method after discovering Nazo's now-deprecated .save() method. Shoutout to Nazo!

How to find documents in all mondays from last 7 weeks in mongodb

{
"_id" : ObjectId("568b650543712795bf864a45")
"companyId" : "55e2d7cfdc8f74d14f5c900f",
"timeStamp" : ISODate("2014-12-02T18:30:00.000Z")
},
{
"_id" : ObjectId("568b650543712795bf864a46")
"companyId" : "55e2d7cfdc8f74d14f5c900f",
"timeStamp" : ISODate("2014-12-03T18:30:00.000Z")
},
{
"_id" : ObjectId("568b650543712795bf864a47")
"companyId" : "55e2d7cfdc8f74d14f5c900f",
"timeStamp" : ISODate("2014-12-04T18:30:00.000Z")
}
retrieve all documents in mondays from timeStamp field from last 7 weeks.
You have to use mongodb aggregation framework to achieve this.
Find date of start (current day - 7 weeks) in whatever programming language you are using.
Then you have to use aggregation operation $dayOfWeek to achieve this
var pipeline = [
{
$match: {timeStamp: {$gte: startDate}}
},
{
$project: {dayOfWeek: {$dayOfWeek: '$timeStamp'}}
},
{
$match: {dayOfWeek: 1}
}
];
db.mycollection.aggreage(pipeline)
In above I have projected only one field, you may do project more fields.
For more information please click $dayOfWeek

Get documents which expired before today in MongoDB

I am using MongoDB 2.6 and I'm making a query that filter the documents by expired date. I want to know which documents expired before today. My persisted data represent publications.
I've made some queries but it doesn't return documents. I know there are many documents who satisfy this condition.
I tried two query but no one works:
1.
{
"domain.ApplicationCase.fields.ExpireDate": { $gte : {
$currentDate: {
lastModified: true,
"cancellation.date": { $type: "timestamp" }
}}}
}
2.
{
"domain.ApplicationCase.fields.ExpireDate": { $gte : new Date()}
}
Part of document records:
{
"_id" : "1234546",
"fields" : {
"Orchestration" : "default",
"Segmentation" : "PFI",
"MatchKey" : "1",
"UserID" : "001"
},
"domain" : {
"ApplicationCase" : {
"_id" : null,
"fields" : {
"ExpireDate" : "2015-11-13T13:47:26Z",
....
What's wrong?
If you want to get records which are expired before today then you should use $lte instead of $gte:
db.myCollection.find({
"domain.ApplicationCase.fields.ExpireDate": { $lte : new Date()}
})
Update:
So the core problem with your documents is that, the value of domain.ApplicationCase.fields.ExpireDate are not in the date format instead they are in simple String format.
So you first need to convert them to the date in order for the query to work since you are comparing an String with the Date.
Probably, you can use a code like this to convert the string to the date:
db.myCollection.find({
"domain.ApplicationCase.fields.ExpireDate": {$exists: true}
}).snapshot().forEach(function(record) {
var stringValue = record.domain.ApplicationCase.fields.ExpireDate;
db.myCollection.update({_id: record._id}, {$set: {
"domain.ApplicationCase.fields.ExpireDate": ISODate(stringValue)
}});
})

Mongoose Mongodb sorting and limiting query of subdocuments

I've got the following design Schema:
{
participants: [String],
conversations: [{
date: Date
messages: [String]
}]
}
Now i want to get the 6 newest converations. I have tried a lot but i can't seem to find the solution. I can sort by subdocuments, but at the end if 1 document has the 6 newest conversations the query will end up giving me this one document plus 5 others. I woud like to get an array like this at the end of the query or be able to get this particular information:
[{date:'Adate', messages:[]},{date:'Adate2',messages:[]}]
Thanks for your help!
Actually this is not possible with the single query if you are a using a mongoDB version LESS than 3.1.6.
$Slice is supported in aggregation pipeline in the mongoDB version 3.1.6 and above
If your mongoDB version is below 3.1.6, then you can try the below piece of code :
db.collection.aggregate([
{ $unwind : "conversations"},
{ $sort : {_id : 1, conversations.date : -1}},
{ $group: { _id : "$_id"} , conversations : { $push : "$conversations"}, participants : {$first : "$participants"} },
{ $project : { _id : 1, conversations : 1, participants : 1 } }
]).forEach( function(doc)
{
if( doc.conversations.length > 6)
{
var count = doc.conversations.length - 6;
doc.conversations.splice(6, count );
}
}
)
There is a similar question on the StackOverflow for the version below 3.1.6, Please check the link.
For the mongoDb Version 3.1.6 and above, you can use $Slice in aggregation pipeline to limit the contents of array.
Try the below code :
db.collection.aggregate([
{ $unwind : "conversations"},
{ $sort : {_id : 1, conversations.date : -1}},
{ $group: { _id : "$_id"} , conversations : { $push : "$conversations"}, participants : {$first : "$participants"} },
{ $project :
{
_id : 1,
participants : 1,
newconversations :
{
conversations : { $slice : 6 }
}
}
}
])

$elemMatch differences in mongo

I'm seeing some differences between 2.0.7 and 2.2.0 when it comes to the $elemMatch operation.
In 2.2.0, I do get results back with this query:
db.testColl.find( { "metadata" : {$elemMatch : {$gt : {age:23}, $lt : {age:99}} }});
In 2.0.7, I don't get any results back.
For testing purposes, I have only one document in my testColl collection:
{
"_id" : ObjectId("4fb2974cbedb4a626109b002"),
"metadata" : [
{
"age" : 59
},
{
"gender" : "FEMALE"
}
]
}
Does anyone know why this works in 2.2.0, but not 2.0.7?
According to this:
http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24elemMatch
elemMatch is supported for v1.4+
Thanks,
Galen
If you're looking for a way that works in both versions, you don't need to use $elemMatch here because you're only comparing against a single field so you can use a simpler query. Try this instead:
db.testColl.find({ 'metadata.age': { $gt: 23, $lt: 99 }});