How do I write a MongoDB shell query that will return the documents for all objects created after a specific date?
Collections like:
{
"_id" : ObjectId("59918c9014450171039b7e1f"),
"cont_id" : "59918c9014450171039b7e1d",
"systemdate" : ISODate("2017-07-25T00:09:00.567Z"),
}
db.itemtable.count({"systemdate" : { $gte: ISODate("2017-07-25T00:00:00.000Z")}})
Returns - 15210
db.itemtable.count({'_id': {'$gt' : ObjectId("59918c9014450171039b7e1f")}})
Returns - 987652
Thanks!
Bharathi
db.itemtable.find({"systemdate" : { $gte: ISODate("2017-07-25T00:00:00.000Z")}}).count()
returns count of those documents.
If you want cursor to those documents, use just find db.itemtable.find({"systemdate" : { $gte: ISODate("2017-07-25T00:00:00.000Z")}})
Related
I'm fairly new to mongodb so please bear with me.
As per title, what I want to achieve is to convert a specific field in all documents within an array of a document from String to Int how do i do that?
Sample Doc :
{
reviews:[
{
snid:"1242"
},
{
snid:"8392"
}
]
}
And my objective is to convert all of the snid's from String to Int32
so far i understand that we can use something like db.collection.update() but this will update a specific field, not an array.
Another attempt is
db.collection.find({},{reviews:1,_id:0},(err,doc)=>{
//How do i push it back to the document
})
But as you can tell, I'm not entirely sure on how we should push the updated document back into the same array of sorts.
Any insights will be greatly appreciated!
1) If you're using MongoDB version >= 4.2, try below query :
db.collection.update({'reviews.snid' : {$exists : true}}, [
{
$set: {
reviews: {
$map: { input: "$reviews", in: { 'snid': { $toInt: "$$this.snid" } } }
}
}
}
],{multi :true})
Above query uses Aggregation-pipeline in .update() which was introduced in version 4.2, You can also use .updateMany() instead of .update().
It works on documents of below type :
/* 1 */
{
"_id" : ObjectId("5e810f5ec16b5679b43a2f0e"),
"reviews" : [
{
"snid" : '1242'
},
{
"snid" : '8392'
}
]
}
/* 2 */
{
"_id" : ObjectId("5e810f6ac16b5679b43a310c"),
"reviews" : [
{
"snid" : '1242232'
},
{
"snid" : '8391232'
}
]
}
/* 3 */
{
"_id" : ObjectId("5e8110b1c16b5679b43a5148"),
"abc" : 1
}
/* 4 */
{
"_id" : ObjectId("5e8110c3c16b5679b43a52f9"),
"reviews" : []
}
/* 5 */
{
"_id" : ObjectId("5e811359c16b5679b43a9229"),
"reviews" : [
{
"abc" : "1"
}
]
}
But above update query will partially work if you've a doc like below :
{
"_id" : ObjectId("5e811359c16b5679b43a9230"),
"reviews" : [
{
"abc" : "1"
},
{
"snid" : "123"
}
]
}
In that case you need to use $cond to do a conditional check in $map to see if current object has key snid then convert value or else pass on the same object as is to 'reviews' array.
2) Just in Case if your MongoDB version is < 4.2/4.0 & > 3.2 - You can use .bulkWrite() :
Cause you can not use Aggregation Pipeline in update & also $toInt. So you need to do .find() to get entire docs & write code to convert these from strings to integers & use .bulkWrite() to update docs in one update DB call (You can take _id as key for each document).
3) You can also write an aggregation query on existing collection & use $out to update entire collection or write aggregation result to new collection by running just one query. I would prefer to temporarily write it to new collection to check data is correct & rename new collection to what ever is existing by naming existing with something ends with _backup used as backup.
In my aggregate query I'm trying to add conditions in the $match statement to return only records within given date range. Without converting to ISOString, I get a set of records that ignores the date range completely. When I convert to ISOString, I get nothing (returns empty set). I've tried using the $and operator, still nothing.
I've tried all the solutions on stack to no avail. Here's my code:
$match: {
$and: [
{'author.id': { $ne: req.user._id }},
{'blurtDate': { $gte: test1.toISOString() }},
{'blurtDate': { $lte: test2.toISOString() }}
]
}
test1 and test2 are correct, I checked them on console log they reflect as follows:
2019-06-02T12:44:39.000Z -- 2019-07-02T12:44:39.928Z
I also tried without the $and operator like so:
$match: {
'author.id': { $ne: req.user._id },
'blurtDate': { $gte: test1.toISOString() },
'blurtDate': { $lte: test2.toISOString() }
}
Which again returns nothing. Any help much appreciated!
EDIT: Wanted to emphasize that test1 and test2 are new date objects:
test1 = new Date(qryDateFrom); //Tried .toISOString() as well
test2 = new Date(qryDateTo);
Without .toISOString(), I get a return of values that ignores the dates. With .toISOString I get an empty return.
Here's an example document that should be returned:
{
"_id" : ObjectId("5d0a807345c85d00ac4b7217"),
"text" : "<p>Seriously RV style.</p>",
"blurtDate" : ISODate("2019-06-19T18:35:31.156Z"),
"blurtImg" : "04643410-92c1-11e9-80b6-a3262311afff.png",
"vote" : 0,
"author" : {
"id" : ObjectId("5cb5df0ef7a3570bb4ac6e05"),
"name" : "Benjamin Paine"
},
"__v" : 0
}
When I remove .toISOString(), I get documents outside of the expected date range, such as this one in May (query should only return between june 2 and july 2).
{
"_id" : ObjectId("5d07ebaf9a035117e4546349"),
"text" : "<p>A start to something more...</p>",
"blurtDate" : ISODate("2019-05-15T19:36:15.737Z"),
"blurtImg" : "2be7a160-9137-11e9-933f-6966b2e503c7.png",
"vote" : 0,
"author" : {
"id" : ObjectId("5cb5df0ef7a3570bb4ac6e05"),
"name" : "Benjamin Paine"
},
"__v" : 0
}
Your docs contain actual Date objects, so remove the .toISOString()s from your query. But you'll also need to combine your $gte and $lte terms into a single object:
$match: {
'author.id': { $ne: req.user._id },
'blurtDate': { $gte: test1, $lte: test2 }
}
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)
}});
})
Let's say i want to return the latest inserted document from the subdocument. I want to be able to return the second record within the tags array w/ the _id of 54a1845def7572cd0e3fe288
So I far I have this query but it returns all values in the tags array.
db.modules.findOne({_id:"ui","svn_branches.branch":"Rocky"},{"svn_branches.$":1})
Mongodb array:
{
"_id" : "ui",
"svn_branches" : [
{
"updated_at" : ISODate("2013-06-12T20:48:17.297Z"),
"branch" : "Rocky",
"revision" : 0,
"tags" : [
{
"_id" : ObjectId("54a178b8ef7572d30e3fe288"),
"commit_message" : "r277 | ssmith | 2015-02-11 17:43:23 -0400 (Wed, 11 Feb 2015)",
"latest_tag" : "20150218r1_6.32_abc",
"revision" : 1,
"tag_revision_number" : "280",
"updated_at" : ISODate("2015-02-18T19:54:54.062Z")
},
{
"_id" : ObjectId("54a1845def7572cd0e3fe288"),
"commit_message" : "r271 | sam | 2dskjh\n",
"latest_tag" : "20150218r2_6.32_abc",
"revision" : 2,
"tag_revision_number" : "281",
"updated_at" : ISODate("2015-02-19T19:54:54.062Z")
}
]
}
]
}
Simple Solution
Let say we have a category as a document and items as a subdocument.
// find document from collection
const category = await Category.findOne({ _id:'$hec453d235xhHe4Y' });
// fetch last index of sub-document
const lastItemIndex = category.items.length - 1;
// here is the last item of sub-document
console.log(category.items[lastItemIndex]);
as mongodb inserted the latest sub-document at last index, so we need to find the last index for the latest sub-doc.
Queries in MongoDB do not return subdocuments (or, as in your case, subdocuments of subdocuments). They match and return the the documents in the collection. The documents' shape can be changed a bit by projection, but it's limited. If you want to find the latest tag commonly, you probably want to make your documents represent tags. Having an array in an array is generally a bad idea in MongoDB, too.
If this is an uncommon operation, and one that doesn't need to be particularly fast, you can use an aggregation:
db.modules.aggregate([
{ "$unwind" : "$svn_branches" },
{ "$unwind" : "$svn_branches.tags" },
{ "$sort" : { "svn_branches.tags.updated_at" : -1 } },
{ "$group" : { "_id" : "$_id", "latest_tag" : { "$first" : "$svn_branches.tags" } } }
])
I needed to find the last entry of subdocuments and I managed to make it to work with the $slice projection operator: mondodb.com > $slice (projection)
db.modules.find({_id:'ui', 'svn_branches.branch':'Rocky'},
{ 'svn_branches.tags': {$slice:-1} } )
I had only one level, if this doesn't work, please let me know.
How to get distinct values from mongodb collection with case insensitive. with given examples I can able to find distinct values.
collection:location schema
{ "_id" : ObjectId("542bc237e75e4a30c2e13b7e"),"place" : ["Hyderabad"]}
{ "_id" : ObjectId("542bc238e75e4a30c2e13b7f"),"place" : ["hyderabad"]}
Example:
from pymongo import MongoClient
MongoClient client = MongoClient('mongodb://localhost:27017/')
db = client.india
collection = db.location
doc = collection.distinct("place")
print doc [[u'Hyderabad'],[u'hyderabad']]
But I need to get only one value as hyderabad, as value being same in two documents.
Why is place an array? I guess you have > 1 values in it sometimes in real documents? Start by unwinding, then use $toLower string operator in an otherwise standard compute-distinct-values aggregation pipeline:
db.test.aggregate([
{ "$unwind" : "$place" },
{ "$group" : { "_id" : { "$toLower" : { "$place" } } } }
])