Unexpected output from map reduce - mongodb

I have the following map and reduce functions that should give me the max date from a group.
Map:
function () {
if (this.topic_id != 0) {
emit(this.topic_id, {date_posted : this.date_posted});
}
}
Reduce:
function (key, values) {
var re_date = ISODate('1970-01-01T00:00:00Z');
values.forEach(function (value) {
if (re_date == ISODate('1970-01-01T00:00:00Z')) {
re_date = value.date_posted;
}
if (re_date < value.date_posted) {
re_date = value.date_posted;
}
});
return {date_posted: re_date};
}
At the moment, it is giving the following output:
{ "_id" : "1", "value" : ISODate("2010-06-01T13:36:30Z") }
{ "_id" : "10", "value" : { "date_posted" : ISODate("2010-05-19T21:33:16Z") } }
{ "_id" : "1000", "value" : { "date_posted" : ISODate("2010-07-04T04:09:43Z") } }
{ "_id" : "1004", "value" : ISODate("2010-07-05T01:27:53Z") }
{ "_id" : "1007", "value" : { "date_posted" : ISODate("2010-07-04T23:44:56Z") } }
{ "_id" : "1009", "value" : ISODate("2010-08-12T19:05:35Z") }
{ "_id" : "1012", "value" : ISODate("2010-08-14T19:56:35Z") }
{ "_id" : "1014", "value" : { "date_posted" : ISODate("2010-07-05T07:18:56Z") } }
{ "_id" : "1022", "value" : ISODate("2010-07-06T21:17:57Z") }
{ "_id" : "1024", "value" : { "date_posted" : ISODate("2010-07-06T12:37:28Z") } }
{ "_id" : "1028", "value" : ISODate("2010-07-08T00:24:59Z") }
{ "_id" : "1029", "value" : ISODate("2010-07-26T12:08:34Z") }
{ "_id" : "1042", "value" : { "date_posted" : ISODate("2010-10-01T19:22:29Z") } }
{ "_id" : "1043", "value" : { "date_posted" : ISODate("2010-07-20T01:38:44Z") } }
{ "_id" : "1048", "value" : { "date_posted" : ISODate("2010-07-08T19:29:14Z") } }
{ "_id" : "1049", "value" : ISODate("2010-07-08T11:07:30Z") }
{ "_id" : "105", "value" : ISODate("2010-05-21T01:53:20Z") }
{ "_id" : "1053", "value" : { "date_posted" : ISODate("2010-07-08T17:53:57Z") } }
{ "_id" : "1056", "value" : { "date_posted" : ISODate("2010-07-08T22:35:02Z") } }
{ "_id" : "1060", "value" : { "date_posted" : ISODate("2010-07-09T06:33:57Z") } }
I was expecting that the value field for every line would always have the "date_posted" element but clearly only some have this. Do I have a mistake in my map function?
A sample of the original data:
db.posts.find({"topic_id" : {$in : ["105", "1053", "1000", "1004", "1007"]}}, {"date_posted" : 1, "topic_id" : 1})
{ "_id" : "1010", "date_posted" : ISODate("2010-07-05T01:27:53Z"), "topic_id" : "1004" }
{ "_id" : "106", "date_posted" : ISODate("2010-05-21T01:52:59Z"), "topic_id" : "105" }
{ "_id" : "107", "date_posted" : ISODate("2010-05-21T01:53:20Z"), "topic_id" : "105" }
{ "_id" : "1001", "date_posted" : ISODate("2010-07-04T04:09:43Z"), "topic_id" : "1000" }
{ "_id" : "1006", "date_posted" : ISODate("2010-07-04T23:21:30Z"), "topic_id" : "1004" }
{ "_id" : "1008", "date_posted" : ISODate("2010-07-04T23:44:56Z"), "topic_id" : "1007" }
{ "_id" : "1054", "date_posted" : ISODate("2010-07-08T17:53:57Z"), "topic_id" : "1053" }

Ok, it looks like my logic for getting the max date is screwed up. I had posted a different question for a related issue and the code posted by William Z in response to that question works better:
function (key, values) {
var re_date = ISODate('1970-01-01T00:00:00Z');
values.forEach(function (val) {
if ( re_date < val.date_posted )
re_date = val.date_posted;
}
);
return {date_posted : re_date}; }

Related

how to update in element array mongodb

I have a exemple data:
"_id" : ObjectId("5694ba11b3957b7ff69c4547"),
"name" : "Okas 1",
"job" : {
"name" : "job try1",
"_id" : ObjectId("5a6ff9f7a336e3bba40a1d5c")
},
"categories" : {
"ss" : [
{
"name" : "10",
"_id" : ObjectId("5a6ff9f7a336e3bba40a1d5c")
},
{
"name" : "50",
"_id" : ObjectId("5a6ff9f7a336e3bba40a1d5f")
}
]
}
if I update with new data .
[{
"name" : "800",
"_id" : ObjectId("5a6ff9f7a336e3bba40a1d5a")
},
{
"name" : "8",
"_id" : ObjectId("5a6ff9f7a336e3bba40a1d5f")
}]
I should get the data
"_id" : ObjectId("5694ba11b3957b7ff69c4547"),
"name" : "Okas 1",
"job" : {
"name" : "job try1",
"_id" : ObjectId("5a6ff9f7a336e3bba40a1d5c")
},
"categories" : {
"ss" : [
{
"name" : "10",
"_id" : ObjectId("5a6ff9f7a336e3bba40a1d5c")
},
{
"name" : "8",
"_id" : ObjectId("5a6ff9f7a336e3bba40a1d5f")
},
{
"name" : "800",
"_id" : ObjectId("5a6ff9f7a336e3bba40a1d5a")
}
]
}
So I want to update if data exeist just update value but if not exist
add new element in to array categories. I try but not working. the
results are not appropriate
You can do something like this:
model.findOne({_id:req.params.id}, (err, data) => {
if (err) throw err;
if(!data) {
var newData = new model({
name: req.body.name
.....
})
newData.save((err, newdata) => {
// Response
})
} else {
data.name = req.body.name
data.save((err, data) => {
// Response
})
}
I hope this is what you want.

need to filter query to get selected object in mongodb

I have the below document.
I want to return "employeedata" containing only those array objects (family, academic etc.) for which status is "current"
{
"_id" : ObjectId("5a1fe7ed1e9fdd17285ac13f"),
"createdby" : "admin",
"details" : [
{
"_id" : ObjectId("5a1fe81f1e9fdd17285ac14a"),
"employeedata" : {
"createddate" : "2017-11-30T11:13:57.290Z",
"family" : [
{
"status" : "current",
"_id" : ObjectId("5a1fe81f1e9fdd17285ac153")
}
],
"academic" : [
{
"status" : "archive",
"_id" : ObjectId("5a1fe81f1e9fdd17285ac159")
},
{
"status" : "current",
"_id" : ObjectId("5a1fe8a71e9fdd17285ac15d")
}
],
"company" : [
{
"status" : "archive",
"_id" : ObjectId("5a1fe81f1e9fdd17285ac150")
},
{
"status" : "current",
"_id" : ObjectId("5a1fe88e1e9fdd17285ac15c")
}
],
"other" : [
{
"status" : "current",
"_id" : ObjectId("5a1fe81f1e9fdd17285ac154")
}
]
}
}
]
"confirmed" : true,
}
You can try following to filter the object as it is an complex object we will have to loop through the complete object and modify it at run time.
var data = JSON.parse('{"_id":"5a1fe7ed1e9fdd17285ac13f","createdby":"admin","details":[{"_id":"5a1fe81f1e9fdd17285ac14a","employeedata":{"createddate":"2017-11-30T11:13:57.290Z","family":[{"status":"current","_id":"5a1fe81f1e9fdd17285ac153"}],"academic":[{"status":"archive","_id":"5a1fe81f1e9fdd17285ac159"},{"status":"current","_id":"5a1fe8a71e9fdd17285ac15d"}],"company":[{"status":"archive","_id":"5a1fe81f1e9fdd17285ac150"},{"status":"current","_id":"5a1fe88e1e9fdd17285ac15c"}],"other":[{"status":"current","_id":"5a1fe81f1e9fdd17285ac154"}]}}]}');
function createObject() {
for (var obj in data.details[0].employeedata) {
if (Array.isArray(data.details[0].employeedata[obj])) {
data.details[0].employeedata[obj].filter(function (value, index) {
if (value.status !== 'current') {
//return value;
data.details[0].employeedata[obj].splice(index, 1);
}
})
}
}
}

Can you combine specific and none-specific fields in mongodb find on embedded documents?

I have embedded documents like
{ a:
{ aa: { aaa: 1, bbb: 2, ccc: 3 },
bb: { aaa: 1, bbb: 2, ccc: 3 },
cc: { aaa: 1, bbb: 2, ccc: 3 }
}
}
How can I write a field filter like:
find({}, { "a.*.aaa": 1 } )
* = aa, bb, cc
In mongodb documentation is no hint (see https://docs.mongodb.com/v3.2/tutorial/project-fields-from-query-results/)
This can be done if you are querying for value. But what you are trying is on the key. We have to give exact match on the key.
We can use $regex to match on value and not on the key.
Let us have a collection
db.collection.find();
{ "_id" : ObjectId("583eed6c911c8e111fb99bf4"), "name" : "a.aa.aaa" }
{ "_id" : ObjectId("583eed72911c8e111fb99bf5"), "name" : "a.bb.aaa" }
{ "_id" : ObjectId("583eed77911c8e111fb99bf6"), "name" : "a.bb.bbb" }
{ "_id" : ObjectId("583eed7b911c8e111fb99bf7"), "name" : "a.cc.bbb" }
{ "_id" : ObjectId("583eed7f911c8e111fb99bf8"), "name" : "a.cc.aaa" }
{ "_id" : ObjectId("583eed84911c8e111fb99bf9"), "name" : "a.cc.bbb" }
{ "_id" : ObjectId("583eed88911c8e111fb99bfa"), "name" : "a.cc.ccc" }
{ "_id" : ObjectId("583eed9a911c8e111fb99bfb"), "name" : "a.aa.ccc" }
{ "_id" : ObjectId("583eeda4911c8e111fb99bfc"), "name" : "a.aa.bbb" }
{ "_id" : ObjectId("583eedfd911c8e111fb99bfd"), "name" : "a.aa.abc" }
{ "_id" : ObjectId("583eee03911c8e111fb99bfe"), "name" : "a.bb.abc" }
{ "_id" : ObjectId("583eee06911c8e111fb99bff"), "name" : "a.cc.abc" }
Then the query using $regex is like
db.collection.find({name:{$regex: /a.*.aa*/}});
and the result of this query
{ "_id" : ObjectId("583eed6c911c8e111fb99bf4"), "name" : "a.aa.aaa" }
{ "_id" : ObjectId("583eed72911c8e111fb99bf5"), "name" : "a.bb.aaa" }
{ "_id" : ObjectId("583eed7f911c8e111fb99bf8"), "name" : "a.cc.aaa" }
{ "_id" : ObjectId("583eed9a911c8e111fb99bfb"), "name" : "a.aa.ccc" }
{ "_id" : ObjectId("583eeda4911c8e111fb99bfc"), "name" : "a.aa.bbb" }
{ "_id" : ObjectId("583eedfd911c8e111fb99bfd"), "name" : "a.aa.abc" }
{ "_id" : ObjectId("583eee03911c8e111fb99bfe"), "name" : "a.bb.abc" }
{ "_id" : ObjectId("583eee06911c8e111fb99bff"), "name" : "a.cc.abc" }
Pls refer: Mongodb - regex match of keys for subobjects
Hope it Helps!

Mongo DB Sorting issue with Ascending order

I have a collection named "formTest123" with following records:
/* 0 */
{
"_id" : ObjectId("5784f5aeef31a98294231459"),
"data" : [
{
"name" : "Amir",
"Other" : [
{
"data" : {
"city" : {
"address" : "pncjj"
}
}
},
{
"data" : {
"state" : {
"address" : "xyz"
}
}
}
]
}
]
}
/* 1 */
{
"_id" : ObjectId("5784f62cef31a9829423145a"),
"data" : [
{
"name" : "Zssmir",
"Other" : [
{
"data" : {
"city" : {
"address" : "bncd"
}
}
},
{
"data" : {
"state" : {
"address" : "gyk"
}
}
}
]
}
]
}
/* 2 */
{
"_id" : ObjectId("5784f636ef31a9829423145b"),
"data" : [
{
"name" : "Cmir",
"Other" : [
{
"data" : {
"city" : {
"address" : "tuhn"
}
}
},
{
"data" : {
"state" : {
"address" : "knm"
}
}
}
]
}
]
}
When I query this collection with:
db.formTest123.find().sort( { "data.Other.data.city.address" : -1})
means in descending order it gives correct output that is :
/* 0 */
{
"_id" : ObjectId("5784f636ef31a9829423145b"),
"data" : [
{
"name" : "Cmir",
"Other" : [
{
"data" : {
"city" : {
"address" : "tuhn"
}
}
},
{
"data" : {
"state" : {
"address" : "knm"
}
}
}
]
}
]
}
/* 1 */
{
"_id" : ObjectId("5784f5aeef31a98294231459"),
"data" : [
{
"name" : "Amir",
"Other" : [
{
"data" : {
"city" : {
"address" : "pncjj"
}
}
},
{
"data" : {
"state" : {
"address" : "xyz"
}
}
}
]
}
]
}
/* 2 */
{
"_id" : ObjectId("5784f62cef31a9829423145a"),
"data" : [
{
"name" : "Zssmir",
"Other" : [
{
"data" : {
"city" : {
"address" : "bncd"
}
}
},
{
"data" : {
"state" : {
"address" : "gyk"
}
}
}
]
}
]
}
But When I query with:
db.formTest123.find().sort( { "data.Other.data.city.address" : 1})
to get in ascending order of "city.address" it gives:
/* 0 */
{
"_id" : ObjectId("5784f5aeef31a98294231459"),
"data" : [
{
"name" : "Amir",
"Other" : [
{
"data" : {
"city" : {
"address" : "pncjj"
}
}
},
{
"data" : {
"state" : {
"address" : "xyz"
}
}
}
]
}
]
}
/* 1 */
{
"_id" : ObjectId("5784f62cef31a9829423145a"),
"data" : [
{
"name" : "Zssmir",
"Other" : [
{
"data" : {
"city" : {
"address" : "bncd"
}
}
},
{
"data" : {
"state" : {
"address" : "gyk"
}
}
}
]
}
]
}
/* 2 */
{
"_id" : ObjectId("5784f636ef31a9829423145b"),
"data" : [
{
"name" : "Cmir",
"Other" : [
{
"data" : {
"city" : {
"address" : "tuhn"
}
}
},
{
"data" : {
"state" : {
"address" : "knm"
}
}
}
]
}
]
}
That is clearly wrong as now records are not sorted in ascending order by "city.address"
Can any one guess what is problem with ascending order?
It is because it is ordering from the "lowest" to the "highest".
Problem is, that undefined and/or null has "lower" value than any existing number.
When you ordering by array, it looks to all documents in that array and takes the minimum value, which is "undefined" in the document, which contains state.
If you for example add "city.address" with high-enough value to all your documents, it will work for ascending. Like this one :
"Other" : [
{
"data" : {
"city" : {
"address" : "tuhn"
}
}
},
{
"data" : {
"state" : {
"address" : "knm"
}
"city" : {
"address" : "zzzzzzzzzzzzzzzzz"
}
}
}
]
Note : For descending, it takes maximum value, therefore it "works", because any city.address override all the null and undefined.
If you need ascending order and dont want to change the data structure, I would suggest to order it descending and then reverse order programically, if it is possible.
Since field "Other" is an array of (sub)documents, we must specify the index of the sub-document.
Based on the schema specified in question, following works.
db.formTest123.find().sort( { "data.Other.0.data.city.address" : 1});
and
db.formTest123.find().sort( { "data.Other.0.data.city.address" : -1});

How can I Pivot on MongoDB

Given the documents:
{
"_id" : "8843c0c0-846f-44ae-9b69-a124dd28f4db",
"purchaseOrderData" : {
"purchaseOrderId" : "WI9ZF"
}
}
{
"_id" : "c3fb80fc-75c0-4259-9d5a-1bc6de1ce7d7",
"purchaseOrderData" : {
"purchaseOrderId" : "WJ0DD"
}
}
{
"_id" : "2ae496e6-28f9-4baa-b952-2054a505f658",
"purchaseOrderData" : {
"purchaseOrderId" : "WI8PP"
}
}
{
"_id" : "421ccbed-0824-443f-bf42-3f0049f46c71",
"purchaseOrderData" : {
"purchaseOrderId" : "WI9WH"
}
}
{
"_id" : "5481b1ef-5f0f-4ba1-8210-d704e9650af4",
"purchaseOrderData" : {
"purchaseOrderId" : "WI9ZH"
}
}
{
"_id" : "1640a27a-6577-4240-8aaa-4c4b1334fd6d",
"purchaseOrderData" : {
"purchaseOrderId" : "WJ0DD"
}
}
{
"_id" : "bd95d801-da2d-4556-a223-dcff30b6ab9d",
"purchaseOrderData" : {}
}
{
"_id" : "4880f816-41e7-43bc-bed4-e8574aa9c045",
"purchaseOrderData" : {
"purchaseOrderId" : "WI9LA"
}
}
{
"_id" : "fe651764-aeb4-460e-89fa-474fcec33f19",
"purchaseOrderData" : {}
}
{
"_id" : "4d73431c-85dc-479a-8739-b314d6cd9636",
"purchaseOrderData" : {
"purchaseOrderId" : "WI9LA"
}
}
i want a result like:
{
"purchaseOrderData.purchaseOrderId":["_id1","_id2"]
}
ex:
[{
"WI9ZF":["8843c0c0-846f-44ae-9b69-a124dd28f4db"]
},{
"WI9WH":["421ccbed-0824-443f-bf42-3f0049f46c71","5481b1ef-5f0f-4ba1-8210-d704e9650af4"]
}]
there was a few question similar to yours befere [1] [2]
using aggregation framework you can achieve a close document shape, but there will be a need to reshape this on app server side.
db.leonardo.aggregate([
{
$group:{
"_id":"$purchaseOrderData.purchaseOrderId",
"data":{$push:"$_id"}
}
}])
will give this output for given dataset:
{ "_id" : "WI9WH", "data" : [ "421ccbed-0824-443f-bf42-3f0049f46c71" ] }
{ "_id" : "WI9ZF", "data" : [ "8843c0c0-846f-44ae-9b69-a124dd28f4db" ] }
{
"_id" : "WJ0DD",
"data" : [
"c3fb80fc-75c0-4259-9d5a-1bc6de1ce7d7",
"1640a27a-6577-4240-8aaa-4c4b1334fd6d"
]
}
{ "_id" : "WI8PP", "data" : [ "2ae496e6-28f9-4baa-b952-2054a505f658" ] }
{ "_id" : "WI9ZH", "data" : [ "5481b1ef-5f0f-4ba1-8210-d704e9650af4" ] }
{ "_id" : null, "data" : [ "bd95d801-da2d-4556-a223-dcff30b6ab9d" ] }
{ "_id" : "WI9LA", "data" : [ "4880f816-41e7-43bc-bed4-e8574aa9c045" ] }