Date comparison in '$where' query not giving expected result - mongodb

I am trying to compare dates in '$where' query to filter data. My 'where' query looks something like this:
function () {
var messageStatusInfoList = this.messageStatusInfoList
var startDate = someDate;
var result = false;
for (var counter = 0; counter < messageStatusInfoList.length; counter++) {
var currentMessageStatusInfo = messageStatusInfoList[counter]
if (counter > 0 && (currentMessageStatusInfo.messageStatus == "RESPONDED" )) {
var responseDate = currentMessageStatusInfo.effectiveDate
if(+responseDate >= +startDate) {
result = true;
break;
}
}
}
return result;
}
Here is sample input document:
{
"_id" : NumberLong(3687),
"messageStatusInfoList" : [
{
"effectiveDate" : ISODate("2014-08-01T13:29:26.456Z"),
"expirationDate" : ISODate("2014-08-04T11:40:29.824Z"),
"messageStatus" : "OPENED"
},
{
"effectiveDate" : ISODate("2014-08-04T11:40:29.824Z"),
"expirationDate" : ISODate("2014-08-05T13:01:00.135Z"),
"messageStatus" : "RESPONDED",
"userId" : NumberLong(8)
},
{
"effectiveDate" : ISODate("2014-08-05T13:01:00.135Z"),
"messageStatus" : "REPLY_TO_CUSTOMER",
"userId" : NumberLong(8)
}
],
"tenantId" : NumberLong(4),
"text" : "some text ..",
"version" : NumberLong(12)
}
As per the above document and given where query, if startDate is set to 2014-08-03, then the date comparison should evaluate to true(because responseDate is 2014-08-04T11:40:29.824Z and responseDate is greater than startDate). But it is not happening so. The comparison operator evaluates to false.

The issue was due to improper initialization of variable startDate in my where query.

Related

ag-grid actualComparator error

i'm building an ag-Grid in Vue.js . I'm trying to set colDefs and dataRow dinamically, and all is ok but i've "actualComparator is not a function" error when i set a date filter.
coldefs are dinamics and i receive from json
colDefs:[
{
"field" : "field1",
"filter" : "text",
"headerName" : "Name",
"width" : 100},
{
"field" : "filed2",
"filter" : "text",
"headerName" : "Surname",
"width" : 80},
{
"field" : "date1",
"filter" : "agDateColumnFilter",
"filterParams" : {
"clearButton" : true,
"comparator" : "dateFilterComparator"
},
"headerName" : "Birth",
"width" : 150
}]
dateFieldComparator is a function inside the methods
dateFilterComparator(filterLocalDateAtMidnight, cellValue){
console.log("I'm here");
var dateAsString = cellValue;
if (dateAsString == null) return -1;
var dateParts = dateAsString.split("/");
var cellDate = new Date(Number(dateParts[2]), Number(dateParts[1]) - 1, Number(dateParts[0]));
if (filterLocalDateAtMidnight == cellDate) {
return 0;
}
else if (cellDate < filterLocalDateAtMidnight) {
return -1;
} else {
return 1;
}
}
The request for the json (dataRow + colDefs) is send on the beforeMount eventhook, ag-grid is showed correctly but when i try to set a filter on the date i receive the error above.
The Clear Filter button is showed but the comparator seems not initialized with my function dataParamComparator.
I've try to call the gridOptions.api.setColumnDefs() on the onReady but without success.
Regards
Davide

whether mongodb mapreduce function accepts calculated value of document as a mapper

I use MongoDB version 2.6.10. Below is the collection structure. I use MapReduce function to group the names of the user based on (created(excluding seconds), event_name.
{
"_id" : ObjectId("59c11d79078dc54153c36ee8"),
"event_name" : "notification",
"created" : ISODate("2017-09-19T13:36:57.252Z"),
"sender_name" : "nathan",
"user_name": "Ragul"",
}
{
"_id" : ObjectId("59c11d79078dc54153c36eeb"),
"event_name" : "notification",
"created" : ISODate("2017-09-19T13:36:57.772Z"),
"sender_name" : "parmesh",
"user_name": "Ram",
}
{
"_id" : ObjectId("59c11d7a078dc54153c36ef0"),
"event_name" : "notification",
"created" : ISODate("2017-09-19T13:36:58.554Z"),
"sender_name" : "nathan",
"user_name": "Ram",
}
{
"_id" : ObjectId("59c11d7a078dc54153c36ef1"),
"event_name" : "message",
"created" : ISODate("2017-09-19T13:36:58.577Z"),
"sender_name" : "nathan",
"user_name": "Ragul"",
}
Below is my query using MapReduce function. My question is whether we can use calculated date as a mapper. Help me with your suggestions
var mapfn = function(){
if (this.event_name == "message"){
name = this.recipient_name
}
else if ((this.event_name == "notification") && (this.other_status == true)){
name = this.sender_name
}
else if ((this.event_name == "notification") && (this.other_status == false)){
name = "You"
}
this.cre = {$subtract:[this.created,{$add:[{$multiply:[{$second:this.created},1000]},{$millisecond:this.created}]}]}
emit({"event_name": this.event_name, "created": this.cre}, name)
}
var redfun = function(key, value){
return Array.append(value)
}
db.getCollection('users').mapReduce(mapfn, redfun, {out: "example"}).find()
Here instead calculating the date using MongoDB expression, I tried to use javascript to eliminate the seconds and then I mapped then its worked.
var mapfn = function(){
if (this.event_name == "message"){
name = this.recipient_name
}
else if ((this.event_name == "notification") && (this.other_status == true)){
name = this.sender_name
}
else if ((this.event_name == "notification") && (this.other_status == false)){
name = "You"
}
this.created.setSeconds(0);
this.created.setMilliseconds(0);
emit({"event_name": this.event_name, "created": this.created}, name)
}
var redfun = function(key, value){
var names = value.join(",")
return names
}
db.users.mapReduce(mapfn, redfun, {out: "example"}).find()

MongoDB - how to dynamically change key

I am new to MongoDB. I was wondering how MongoDB implements "variable Interpolation" ?
I have following code
for (i=0;i<3;i++){
db.test2.insert({i:i+1});
}
Which insert
{ "_id" : ObjectId("564a1bd0987fe676b9cad025"), "i" : 1 }
{ "_id" : ObjectId("564a1bd0987fe676b9cad026"), "i" : 2 }
{ "_id" : ObjectId("564a1bd0987fe676b9cad027"), "i" : 3 }
But I want
{ "_id" : ObjectId("564a1bd0987fe676b9cad025"), "0" : 1 }
{ "_id" : ObjectId("564a1bd0987fe676b9cad026"), "1" : 2 }
{ "_id" : ObjectId("564a1bd0987fe676b9cad027"), "2" : 3 }
Mongo does not changes value in key part. How to fit it?
You will need to build your query dynamically.
var documents = [];
for(var i=0; i<3; i++) {
var doc = {};
doc[i] = i;
documents.push(doc);
}
db.collection.insert(documents)
Then db.collection.find() yields:
{ "_id" : ObjectId("564a2296c68c7068c12fb206"), "0" : 0 }
{ "_id" : ObjectId("564a2296c68c7068c12fb207"), "1" : 1 }
{ "_id" : ObjectId("564a2296c68c7068c12fb208"), "2" : 2 }
Note that it's not a good practice to have string of integer as field's name

MongoDB Map - Reduce result not exactly

I had data structure in MongoDB as below
{
"_id" : ObjectId("523aab00045624a385e5f549"),
"name" : "English Book 29",
"SKU" : 1000549081,
"price" : 249000,
"image" : null,
"category_id" : ObjectId("523a7802b50418baf38b4575"),
"category_name" : "English Book",
"details" : {
"Title" : "Title 549081",
"Binding" : 1,
"Author" : "Author 0",
"Publication data" : 0.5263832447608386,
"Publisher name" : "Publisher name 14",
"Number of page" : 90
}
}
Binding of book has 2 values:
0 that means soft binding, and 1 that means hard binding. I write Map Reduce to statistics for each values.
var map = function()
{
for(var key in this.details)
{
if(key == 'Binding')
{
emit({name: key}, {
'data':
[
{
name: this.details[key],
count: 1
}
]
});
}
}
};
var reduce = function (key, values) {
var reduced = {};
for(var i in values)
{
var inter = values[i];
for(var j in inter.data)
{
if(typeof(reduced[inter.data[j].name]) != "undefined")
{
reduced[inter.data[j].name] += inter.data[j].count;
}
else
{
reduced[inter.data[j].name] = 1;
}
}
}
return reduced;
};
When I run with small data (50 records) result return exactly. But when I run it with real data (192000 records) result return Not exactly. The result as below
{
"_id" : {
"name" : "Binding"
},
"value" : {
"0" : 50,
"1" : 50
}
}
I checked return data when Map/Reduce done, result as below
"counts" : {
"input" : 192000,
"emit" : 192000,
"reduce" : 1920,
"output" : 1
},
What wrong with it. Welcome any suggestion, explanation.
Thanks and best regards,
After researching about Map/Reduce yesterday, I realized that, "Emit" send 100 elements once, and "Reduce" perform on this data set. So my above code is wrong because it only "SUM" on small data set.
Below that is my new code for Map-Reduce
var map = function ()
{
for(var key in this.details)
{
if(key == 'Binding')
{
var value = {};
value[this.details[key]] = 1;
emit(key, value);
}
}
}
var reduce = function (key, values)
{
var reduced = {};
for(var idx = 0; idx < values.length; idx++)
{
var inner = values[idx];
for (var j in inner)
{
if (typeof (reduced[j]) == 'undefined')
{
reduced[j] = 0;
}
reduced[j] += inner[j];
}
}
return reduced;
}
I post here for anyone who meet similar situation. Thanks for reading.

MongoDB : query collection based on Date

I have a collection in MongoDB in this format
db.logins.find().pretty()
{
"cust_id" : "samueal",
"created_at" : "2011-03-09 10:31:02.765"
}
{
"cust_id" : "sade",
"created_at" : "2011-03-09 10:33:11.157"
}
{
"cust_id" : "sade",
"created_at" : "2011-03-10 10:33:35.595"
}
{
"cust_id" : "samueal",
"created_at" : "2011-03-10 10:39:06.388"
}
This is my mapReduce function
m = function() { emit(this.cust_id, 1); }
r = function (k, vals) { var sum = 0; for (var i in vals) { sum += vals[i]; } return sum; }
q = function() {
var currentDate = new Date();
currentDate.setDate(currentDate.getDate()-32);
var month = (currentDate.getMonth() < 10 ? "0"+ (currentDate.getMonth()+1) : (currentDate.getMonth()+1));
var date = currentDate.getFullYear() + "-" + month ;
var patt = new RegExp(date);
var query = {"created_at":patt};
return query;
}
res = db.logins.mapReduce(m, r, { query : q(), out : "userLoginCountMonthly" });
With this i am geting the output as
{ "_id" : "sade", "value" : 2 }
{ "_id" : "samueal", "value" : 2 }
but i need genearte a Report output in this format
For Example
Name Date Logins
sade 2011-03-09 1
sade 2011-03-10 2
samueal 2011-03-09 1
samueal 2011-03-10 1
Could anybody please help me how to achive , its
Edited Part
Currently I am getting the output as
{ "_id" : "dsstest 2011-03-09", "value" : 4 }
{ "_id" : "dsstest 2011-03-10", "value" : 14 }
Is it possible that i can get in this format
{ "_id" : "dsstest" , "date" : "2011-03-09", "value" : 4 }
{ "_id" : "dsstest" , "date" : "2011-03-10", "value" : 14 }
Your mapping function is insufficient as it doesn't produce key that has the date in it.
I also don't quite understand why in the sample of what you want sade gets two logins. From what you are saying you want, you should need:
var m = function() {
var aux = this.created_at.indexOf(' ');
aux = this.created_at.substring(0,aux);
// this 'if' block will filter out the entries you don't want
// to be included in the result.
if (aux < "2011-11-11") {
return;
}
emit({cust:this.cust_id,day:aux},1);
}
var r = function(k, values) {
var l = values.length;
var r = 0;
var i;
for (i=0; i<l; i++) {
r+=values[i];
}
return r;
}
And to run:
> db.logins.mapReduce(m, r, { query : q(), out : "userLoginCountMonthly" });
And finally, to produce the report:
> db.userLoginCountMonthly.find().forEach(function(e){print(e._id.cust +' ' + e._id.day+' '+e.value);})
This would list the amount of logins for each user, for each day (within your search scope).