MongoDB $gt not working - mongodb

Below query gives me no results, though there are fields matching the geo location and time stamp.
I have tried changing the $gt to $ne and it returns the sum of all $values.
I have even tried checking timeStamp greater than 0. still no result. Here timestamp is a double datatype.
db.csv2.aggregate([{
$match: {
$and: [{
loc: {
$geoWithin: {
$box: [
[-128.232422, 26.382028],
[-109.6875, 43.624147]
]
}
}
}, {
timeStamp: {
$gt: 1432201420790
}
}]
}
}, {
$group: {
_id: null,
total: {
$sum: "$value"
}
}
}]);

The error given to you is explicit. Read the doc to see how to implement the $gt aggregation function : documentation
Basically, the condition is an array
{ $gt: ["$timeStamp", 1432201420790] }
[EDIT]
Your issue probably comes from the syntax with the dollar sign before the timestamp field which is missing in your code. Try this
{ $gt: ["$timeStamp", 1432201420790] }
instead of
{ timeStamp: { $gt: 1432201420790 }}

Related

MongoDB - Dates between using $match

So I try to use MongoDB $match to get data between 2 dates, but it turns out that the data is not returning a.k.a empty here. What it looks like:
db.collection.aggregate([
{
$match: {
date: {
$gte: new Date("2022-10-23"),
$lt: new Date("2022-10-25"),
},
}
},
{
$group: {
_id: "$title",
title: {
$first: "$title"
},
answer: {
$push: {
username: "$username",
date: "$date",
formId: "$formId",
answer: "$answer"
}
}
}
},
])
Here is the data that I try to run on the Mongo playground:
https://mongoplayground.net/p/jKx_5kZnJNz
I think there is no error with my code anymore... but why it gives an empty return.
Migrate the comment to the answer post for the complete explanation.
Issue 1
The document contains the date field as a string type while you are trying to compare with Date which leads to incorrect output.
Ensure that you are comparing both values in the exact type.
Either that migrate the date value to Date type or
converting the date field to Date type in the query via $toDate.
{
$match: {
$expr: {
$and: [
{
$gte: [
{
$toDate: "$date"
},
new Date("2022-10-23")
]
},
{
$lt: [
{
$toDate: "$date"
},
new Date("2022-10-25")
]
}
]
}
}
}
Issue 2
Since you are using $lt ($lt: new Date("2022-10-25")), it won't include the documents with date: new Date("2022-10-25").
For inclusive end date, you shall use $lte.
Demo # Mongo Playground

Get document on subarray containing date between aggregation mongodb

Provided following collection:
[
{
events: [
{
triggers: [
{
date: "2019-12-12T23:00:00"
}
]
}
]
}
]
I want to be able to pull the documents that have any date in between a range of dates, let's say today and tomorrow.
Using following query:
db.collection.aggregate([
{
$match: {
"events.triggers.date": {
$gte: "2019-12-11T23:00:00.000Z",
$lt: "2019-12-12T23:59:00.000Z"
}
}
}
]);
However, when I do this, the query seems to be looking at any document that has any date greater than and any date lower than but not necessarily in the same "trigger" object.
Anyone got any idea how you can filter in a subarray like this (I do more in my query afterwards so a find will not work) and have the date search be subitem specific?
You are almost there, just some mistakes in your query. This should work:
db.collection.aggregate([
{
'$match': {
'$and': [
{"events.triggers.date": { '$gte': "2019-12-11T23:00:00.000Z" }},
{"events.triggers.date": { '$lt': "2019-12-11T23:00:00.000Z" }}
]
}
}
]);
So I found it eventually.
Those looking for the solution. Here it is:
elemMatch
db.collection.aggregate([
{
$match: {
"events.triggers": {
$elemMatch: {
"date": {
$gte: "2019-12-11T23:00:00.000Z",
$lt: "2019-12-12T23:59:00.000Z"
}
}
}
}
}
]);

how to convert epoch time stored in nested field to date mongodb

I have a nested field msgs.crtDtTm inside a mongodb which has epoch date (1554120000)stored as string. I need to convert msgs.crtDtTm to Date format to apply $gte (which is not working in String format).
cond: { $gte: [ "$msg.crtDtTm", "1554120000" ] }
I tried this but greater than operation not performed. It is returning all the nested elements without filtering.
You can convert string to date by this command :
new Date("1554120000")
Like this :
db.YourCollection.find({"created_at" : { $gte : new Date("1554120000") }});
in your example :
cond: {$msg.crtDtTm : { $gte: new Date("1554120000") }}
Let me know the result please .
This link is also useful
Once your time april 1,2019 being converted into ms and then to type of string in your code, it would be easy that way(as converting one element vs n values in DB - altogether it might be easy for that format to be converted into ms in code), then use this query to retrieve elements that match your criteria :
db.yourCollection.aggregate([
{$match: {'msgs.crtDtTm': {$gt: '1554120000'}}},
{$addFields: {
msgs: {$filter: {
input: '$msgs',
as: 'msg',
cond: {$gt: ['$$msg.crtDtTm', '1554120000']}
}}
}}
])
You could achieve similar using $unwind on msgs & then $match finally $group or $match to start with, which ever is feasible you can go ahead. Something like this :
db.yourCollection.aggregate([{
$match: {
'msgs.crtDtTm': { $gt: '1554120000' }
}
},
{ $unwind: "$msgs" },
{
$match: {
'msgs.crtDtTm': { $gt: '1554120000' }
}
}, { $group: { _id: '$_id', msgs: { $push: '$msgs' }, docs: { $first: '$$ROOT' } } }, { $addFields: { 'docs.msgs': '$msgs' } }, { $replaceRoot: { newRoot: '$docs' } }])
Lastly, It would be a better idea if you can store the same format which will be used to query.

How to find records in a bson object

var otherLanguages=[ "English","Arabic","French"];
var first, second;
db.collection.find({ $and: [ { "Language" : { $nin : otherLanguages} },{"Language":{ $ne:null}} ]}).forEach(function(obj){
shell out 341 docs one by one. In these docs,I want to find out documents that satisfy two if statements. Later, I want to collect the count it.
if (obj.find({ $and: [{'POS': { $eq: "Past" } },{'Desp': { $ne: null } }] })) { first= first+1;}
if (obj.find({ $and: [{'POS': { $eq: "Past" } },{'Desp': { $eq: null } }] })) {second= second+1;}
});
print (first,second)
I know that I cannot use find() function on the obj, but Is there a way to search on this "bson obj" to find the count.
If this is not feasible, then please suggest a way to get the desired result.
If I understand your question correctly you can achieve that by using the aggregation framework like so:
db.collection.aggregate({
// filter out all documents that you don't care about
$match: {
"Language": { $nin: otherLanguages, $ne: null },
"POS": "Past"
},
}, {
// then split into groups...
$group: {
_id: { $eq: [ "$Desp", null ] }, // ...one for the "eq: null" and one for the "ne: null"
"count": { $sum: 1 } // ...and count the number of documents in each group
}
})

MongoDB exception Resolving [duplicate]

I am getting an issue for running the following aggregate query:
db.snippets.aggregate([ { '$project': { month: { '$month': '$created_at' }} } ])
The error message for the same is:
assert: command failed: {
"errmsg" : "exception: can't convert from BSON type EOO to Date",
"code" : 16006,
"ok" : 0 } : aggregate failed
How do I get around this issue? I found a related question: MongoDB: can't convert from BSON type EOO to Date.
But it doesn't tell me how to get things done.
You likely have one or more docs with a created_at value that's not a BSON Date and you'll need to fix that by converting those values to Date or removing them.
You can find those docs with a $not query that uses the $type operator like:
db.snippets.find({created_at: {$not: {$type: 9}}})
If the created_at values are date strings, you can find the docs that need updating and then update them in the shell using code like:
db.snippets.find({created_at: {$not: {$type: 9}}}).forEach(function(doc) {
// Convert created_at to a Date
doc.created_at = new Date(doc.created_at);
db.snippets.save(doc);
})
try this one, its help for me above problem.
db.snippets.aggregate([{
'$project': {
month: { $substr: ["$created_at", 5, 2] }
}
}]);
above code get month wise
data is entered into the database in ISO format which can then be easily worked with.
In some situations, some documents are supposed to have empty Date fields. In those cases, you could try this (using your example):
db.snippets.aggregate([ { '$project': { month:
{ $cond: [{ $ifNull: ['$created_at', 0] }, { $month: '$created_at' }, -1] }} } ])
In this example, we would get -1 in the cases whenever no field '$created_at' is found. For all the other cases, we would get the Date month.
I had a related issue, but in my case the Date fields were the members of an array, so the error was "can't convert BSON type Object to Date".
I needed to get the day of week from the dates in the possibleTripDateTimes array.
Sample document:
{
"possibleTripDateTimes" : [
{
"tripDateTime" : ISODate("2015-08-01T06:00:00.000-0700")
}
]
}
The fix was simply to use dot notation to address the array member fields.
db.trips.aggregate([
{
$project: {
departTime: {
$map: {
input: "$possibleTripDateTimes.tripDateTime",
as: "dateTime",
in: { $dayOfWeek: "$$dateTime" }
}
}
}
}
]
);
I hope this helps someone who also gets zero search results on the "BSON type Object" search
I had the same problem, I figured that the date field is missing for some of the documents causing the conversion to fail. I just added a match clause to filter these out. But ofcourse i am investigating on my app side why they are not being populated.
db.snippets.aggregate([
{
'$match': {
'created_at': {
"$exists": true
}
}
},
{
'$project': {
month: {
'$month': '$created_at'
}
}
}
])
I had a similar problem, and solved it checking if the date existed.
db.users.aggregate([
{$project:{day: { $cond: ["$bd", { $dayOfMonth: "$bd" }, -1] },
month: { $cond: ["$bd", { $month: "$bd" }, -1] },
year: { $cond: ["$bd", { $year: "$bd" }, -1] }
}},
{$match:{"month":1, "day":15}}
])
My date field is bd and with that match I'm getting all users that have their birthday on January 15th.
This error can also appear if you have incorrectly named your properties in your aggregation relative to what they are in your database.
For example my code was
$group: {
_id: {$week: "$projects.timeStamp"},
total: { $sum: "$projects.hours" }
}
But I hadn't camelcased timestamp in my database so simply modifying to projects.timestamp fixed it.
First, you need to check whether the data type is in ISODate. IF not you can change the data type as the following example.
db.collectionName.find().forEach(function(each_object_from_collection){each_object_from_collection.your_date_field=new ISODate(each_object_from_collection.your_date_field);db.collectionName.save(each_object_from_collection);})
Now you can find it in two ways
db.collectionName.find({ $expr: {$eq: [{ $year: "$your_date_field" }, 2017]}});
Or by aggregation
db.collectionName.aggregate([{$project: {field1_you_need_in_result: 1,field12_you_need_in_result: 1,your_year_variable: {$year: '$your_date_field'}, your_month_variable: {$month: '$your_date_field'}}},{$match: {your_year_variable:2017, your_month_variable: 3}}])
First, you can identify the particular field which is causing an issue as follows:
db.collectionName.find( { 'dateField' : { $type : 2 } } )
The above line checks and finds all the documents with field name 'dateField' having type as String(referred as $type - 2).
Once it is identified and verified, we can modify those records as follows:
db.collectionName.find( { 'dateField' : { $type : 2 } } ).forEach( function (x) {
x.dateField = new ISODate(x.dateField);
db.collectionName.save(x);
});
In my case I had to use "$toDate" and it worked:
db.snippets.aggregate([ { '$project': { month: { '$month': {$toDate: '$created_at'} }} } ])