MongoDB Shell: How to Update a Collection from a Collection - javascript

I have two collections: links and children.
Links has values like this:
> db.links.find().pretty()
{ "_id" : ObjectId("567374999df36aeeda6f2a5f"), "EID" : 1, "CID" : 1 }
{ "_id" : ObjectId("567374999df36aeeda6f2a60"), "EID" : 1, "CID" : 3 }
{ "_id" : ObjectId("567374999df36aeeda6f2a61"), "EID" : 2, "CID" : 5 }
Children has values like this:
{
"_id" : ObjectId("567382709df36aeeda6f2a7e"),
"CID" : 2,
"Cname" : "Mo",
"Age" : 11
}
{
"_id" : ObjectId("567382709df36aeeda6f2a7f"),
"CID" : 3,
"Cname" : "Adam",
"Age" : 13
}
{
"_id" : ObjectId("567382709df36aeeda6f2a80"),
"CID" : 4,
"Cname" : "Eve",
"Age" : 21
}
It seems like this should add EID to children where CID matches between links and children, but it does nothing.
db.children.find().forEach(function (doc1) {
var doc2 = db.links.find({ id: doc1.CID });
if (doc2.CID == doc1.CID) {
doc1.EID = doc2.EID;
db.children.save(doc1);
}
});
This sets the value of EID in children to the value of EID from links where the value of CID in children == 14.
db.children.find().forEach(function (doc1) {
var doc2 = db.links.find({},{_id: 0, CID: 1});
if (doc1.CID == 14) {
doc1.EID = doc1.CID;
db.children.save(doc1);
}
});
{
"_id" : ObjectId("567382709df36aeeda6f2a8a"),
"CID" : 14,
"Cname" : "George II",
"Age" : 12,
"EID" : 14
}
So, it seems like that the equality operation in Javascript (doc2.CID == doc1.CID) isn't working. Why won't this work? I assume I have the syntax wrong or am using the wrong equality operation or operator?

var doc2 = db.links.find({ id: doc1.CID });
doc2 here is a cursor, not the document itself. So you need to go through documents in the cursor.
Try the following code:
db.children.find().forEach(function (doc1) {
var doc2 = db.links.find({CID:doc1.CID}).forEach(function(doc2){
doc1.EID = doc2.EID;
db.children.save(doc1);
})
})

Related

Access title inside id

I am having trouble to access title inside an ID object.
I want to access item.title. But i am not able to give a name to the object ID.
I tried doing order.cart.items.item.title
"_id" : ObjectId("5d60d1752cda6403e4f868af"),
"created_at" : ISODate("2019-08-24T05:55:34.741Z"),
"user" : ObjectId("5d60d00e4c865312ccf3f18a"),
"cart" : {
"items" : {
"5d60cddb69f460191c680e96" : {
"item" : {
"_id" : "5d60cddb69f460191c680e96",
"imagePath" : "https://dks.scene7.com/is/image/GolfGalaxy/18NIKWRMX270XXXXXLFS_Black_Cream?wid=1080&fmt=jpg",
"title" : "Nike ",
"description" : "Nike Airmax",
"price" : 10,
"category" : "shoes",
"__v" : 0
},
"qty" : 1,
"price" : 10
}
},
"totalQty" : 1,
"totalPrice" : 10
},
You need to use Object.values for that, because of the ID. This allows you to get the object with the key of 5d60cddb69f460191c680e96 without the key:
Object.values(order.cart.items)[0].item.title
const data = {
"cart" : {
"items" : {
"5d60cddb69f460191c680e96" : {
"item" : {
"_id" : "5d60cddb69f460191c680e96",
"imagePath" : "https://dks.scene7.com/is/image/GolfGalaxy/18NIKWRMX270XXXXXLFS_Black_Cream?wid=1080&fmt=jpg",
"title" : "Nike ",
"description" : "Nike Airmax",
"price" : 10,
"category" : "shoes",
"__v" : 0
},
"qty" : 1,
"price" : 10
}
},
"totalQty" : 1,
"totalPrice" : 10
}};
for (let id in data.cart.items)
console.log(data.cart.items[id].item.title);
You can simply achieve this by getting key name of an object using Object.keys() methods, This methods returns an array of key names
const obj = { id: 1 };
const keysArray = Object.keys(obj);
console.log(keysArray);. // ["id"]
In your case only one keys are present in the object, So we can directly get that name with index 0 (Object.keys(obj)[0])
Check below snippet
const cart ={
"items": {
"5d60cddb69f460191c680e96": {
"item": {
"_id":
"5d60cddb69f460191c680e96",
"imagePath": '',
"title": "Nike ",
"description": "Nike",
"price": 10,
"category": "shoes",
"__v": 0
},
"qty": 1,
"price": 10
}
}
};
const id =
Object.keys(cart.items)[0];
console.log(
cart.items[id].item.title
);

How to remove document in two different collection using same id at same time in mongodb on feathers application

I'm trying to remove document in two different collection using same id at same time. Is there any possibilities?
user collection:
{
"_id" : ObjectId("5a310315f685dd5038fecaaa"),
"userId" : 3,
"accountId" : 1,
"userType" : "DRIVER",
"firstName" : "Karthi",
"lastName" : "keyan",
"email" : "karthikeyan.a1#gmail.com",
"password" : "$2a$12$KFYc6riMnqTuzXhR0ssKZQmejAU4RF8FthAIQD4sgOUcALesp7DaJxK",
"phone" : "xyz",
"updatedAt" : ISODate("2017-12-13T10:38:13.492Z"),
"createdAt" : ISODate("2017-12-13T10:38:13.492Z"),
"__v" : 0
}
worker collection:
{
"_id" : ObjectId("5a310315f685dd5038fecaab"),
"workerId" : 1,
"accountId" : 1,
"name" : "Karthikeyan",
"email" : "karthikeyan.a1#gmail.com",
"mobile" : "xyz",
"type" : "DRIVER",
"joinDate" : ISODate("2017-12-13T10:38:13.070Z"),
"assignedVehicleId" : "23423231",
"licenseNumber" : "TN2506",
"createdBy" : "1",
"createdDate" : ISODate("2017-12-13T10:38:13.070Z"),
"updatedBy" : "1",
"updatedDate" : ISODate("2017-12-13T10:38:13.070Z"),
"regularHours" : 3600,
"regularRates" : 1500,
"overtimeRates" : 400,
"distanceRate" : 1000,
"stopRate" : 50,
"workerStatus" : "AVAILABLE",
"userId" : 3,
"__v" : 0
}
now i want to remove these two document at same time using userId.
Database adapters allow to call remove with null and a query that will remove all entries matching that query (see the documentation). In your case:
app.service('users').remove(null, { query: { userId: 3 } });
app.service('workers').remove(null, { query: { userId: 3 } });
Removing related entries (e.g. remove all workers for that user once the user has been removed) can be done in an after hook:
app.service('users').hooks({
after: {
async remove(context) {
const user = context.result;
await context.app.service('workers').remove(null, {
query: { userId: user.userId }
});
}
}
});

Javascript: Split array of arrays into multiple arrays

serious problem here, I have an array like this:
[[0,50],[0,68],[1,26],[2,9],[2,32]]
The form I need is to split this array into two separated arrays like this:
array1 = [[0,50][1,0][2,9]]
array2 = [[0,68][1,26][2,32]]
Yeah you are right guys, I need that to build flot chart.
If anybody interested in source of data this is how it looks in firebase:
{
"1433203200000" : {
"-JpgJnANTpQFprRieImv" : {
"events" : 5,
"name" : "Home office",
"returningVisitors" : 9,
"totalVisitors" : 50
},
"-JqsQjFTjHpzKqWgE_KJ" : {
"events" : 10,
"name" : "Samin Place",
"returningVisitors" : 32,
"totalVisitors" : 68
}
},
"1433289600000" : {
"-JqsQjFTjHpzKqWgE_KJ" : {
"name" : "Samin Place",
"newVisitors" : 1,
"returningVisitors" : 25,
"totalVisitors" : 26
}
},
"1433376000000" : {
"-JpgJnANTpQFprRieImv" : {
"events" : 5,
"name" : "Home office",
"returningVisitors" : 9,
"totalVisitors" : 9
},
"-JqsQjFTjHpzKqWgE_KJ" : {
"events" : 10,
"name" : "Samin Place",
"returningVisitors" : 32,
"totalVisitors" : 32
}
}
}
The point is loop each timestamp and each child, there we have totalVisitors that's the value I need for my chart.
BONUS
As you can see first timestamp have two childs thats fine, but second timestamp have only one child - "-JqsQjFTjHpzKqWgE_KJ" so I need to add null value for missing one into new array (in our example it's array1 second position).
That's what I'm calling CHALLENGE :)
Any help is very appreciated, thanks for attention.
Edit:
maybe if it can help to someone this is chart which I need
here is link
X-axis - are timestamps
Y-axis - totalVisitors value
Lines - every unique timestamp child
I created jsfiddle for you. Please tell, is it what you need?
http://jsfiddle.net/1vdryy3L/1/
// first, we'll get all possible keys ('key' is e.g. "-JpgJnANTpQFprRieImv")
var keys = [];
for (var i in data) {
for (var j in data[i]) {
if (keys.indexOf(j) == -1) {
keys.push(j);
}
}
}
var result = {}, tmp, k;
for (i in keys) {
tmp = []; k = 0;
for (var j in data) {
if (data[j][keys[i]]) {
tmp.push([k, data[j][keys[i]].totalVisitors]);
} else {
tmp.push([k, 0]);
}
k++;
}
result['array' + i] = tmp;
}
console.log(JSON.stringify(result));
Something like this should work provided that you are using jQuery. If you are not simply replace the jquery statements with standard js ones. (I have prepared a jsfiddle: jsfiddle:
var first = []
var second = [];
var my_data = {
"1433203200000" : {
"-JpgJnANTpQFprRieImv" : {
"events" : 5,
"name" : "Home office",
"returningVisitors" : 9,
"totalVisitors" : 50
},
"-JqsQjFTjHpzKqWgE_KJ" : {
"events" : 10,
"name" : "Samin Place",
"returningVisitors" : 32,
"totalVisitors" : 68
}
},
"1433289600000" : {
"-JqsQjFTjHpzKqWgE_KJ" : {
"name" : "Samin Place",
"newVisitors" : 1,
"returningVisitors" : 25,
"totalVisitors" : 26
}
},
"1433376000000" : {
"-JpgJnANTpQFprRieImv" : {
"events" : 5,
"name" : "Home office",
"returningVisitors" : 9,
"totalVisitors" : 9
},
"-JqsQjFTjHpzKqWgE_KJ" : {
"events" : 10,
"name" : "Samin Place",
"returningVisitors" : 32,
"totalVisitors" : 32
}
}
}
var count = 0;
$.each(my_data, function(key, value){
if (value["-JpgJnANTpQFprRieImv"]){
first.push([count, value["-JpgJnANTpQFprRieImv"]["totalVisitors"]])
} else {
first.push([count, 0])
}
if (value["-JqsQjFTjHpzKqWgE_KJ"]){
second.push([count, value["-JqsQjFTjHpzKqWgE_KJ"]["totalVisitors"]])
} else {
second.push([count, 0])
}
count++;
});

mongodb update on JSON array

I have this data in Mongo:
{'_id':1,
'name':'Root',
'taskId':1,
'parentId':"",
'path':[1],
'tasks':[ {"taskId":3,parentId:1,name:'A',type:'task'},
{"taskId":4,parentId:1,name:'D',type:'task'},
{"taskId":5,parentId:4,name:'B',type:'task'},
{'type':'project' , 'proRef':2},
{"taskId":6,parentId:3,name:'E',type:'task'},
{"taskId":7,parentId:6,name:'C',type:'task'}]
}
Now I want to update taskId 6 with new Json data .
var jsonData = {"taskId":6,"name":'Sumeet','newField1':'Val1','newField2':'Val2'}
query should update if field is available else add new key to existing .Output Like
{"taskId":6,parentId:3,name:'Sumeet',type:'task','newField1':'Val1','newField2':'Val2'}]
I have tried few query but it is completely replacing json .
db.projectPlan.update({_id:1,'tasks.taskId':6},{$set :{'tasks.$':jsonData }});
Thanks in advance for your helps!
Sumeet
You need to transform the jsonData variable into something that can be passed to update. Here's an example that does exactly what you want with your sample document:
var updateData = {};
for (f in jsonData) {
if (f != "taskId") updateData["tasks.$."+f]=jsonData[f];
};
db.projectPlan.update({_id:1, 'tasks.taskId':6}, {$set:updateData})
Result:
{ "_id" : 1,
"name" : "Root",
"taskId" : 1,
"parentId" : "",
"path" : [ 1 ],
"tasks" : [
{ "taskId" : 3, "parentId" : 1, "name" : "A", "type" : "task" },
{ "taskId" : 4, "parentId" : 1, "name" : "D", "type" : "task" },
{ "taskId" : 5, "parentId" : 4, "name" : "B", "type" : "task" },
{ "type" : "project", "proRef" : 2 },
{ "taskId" : 6, "parentId" : 3, "name" : "Sumeet", "type" : "task", "newField1" : "Val1", "newField2" : "Val2" },
{ "taskId" : 7, "parentId" : 6, "name" : "C", "type" : "task" }
] }
You will need to merge the document manually:
var jsonData = {"taskId":5,"name":'Sumeet','newField1':'Val1','newField2':'Val2'};
db.projectPlan.find({ _id: 1 }).forEach(
function(entry) {
for (var taskKey in entry.tasks) {
if (entry.tasks[taskKey].taskId === jsonData.taskId) {
printjson(entry.tasks[taskKey]);
for (var taskSubKey in jsonData) {
entry.tasks[taskKey][taskSubKey] = jsonData[taskSubKey];
}
printjson(entry.tasks[taskKey]);
}
}
db.projectPlan.save(entry);
}
);
Obviously you can leave away the printjson statements. This is simply to see that the merging of the original tasks with the new tasks works. Note that this query will only update a single document as long as the _id field is unique.

Mongodb mapreduce iterate through object's key value pairs

I have a mongodb collection that has the following data :
{ "_id" : ObjectId("4da31b8b5ba19e3c11345a66"), "USERID" : 4, "datekey" : "BIBAK", "balancekey" : "MAIYM" }
{ "_id" : ObjectId("4da31b8b5ba19e3c12345a66"), "USERID" : 4, "datekey" : "QOTWH", "balancekey" : "SFEYQ" }
{ "_id" : ObjectId("4da31b8b5ba19e3c14345a66"), "USERID" : 4, "datekey" : "TLWJJ", "balancekey" : "RDKAM" }
{ "_id" : ObjectId("4da31b8b5ba19e3c15345a66"), "USERID" : 5, "emailadress" : "KBDIJD" }
{ "_id" : ObjectId("4da31b8b5ba19e3c16345a66"), "USERID" : 1, "accountname" : "KL", "weblink" : "GJ", "note" : "KP" }
{ "_id" : ObjectId("4da31b8b5ba19e3c17345a66"), "USERID" : 1, "accountname" : "WD", "weblink" : "SZ", "note" : "CL" }
{ "_id" : ObjectId("4da31b8b5ba19e3c18345a66"), "USERID" : 1, "accountname" : "IK", "weblink" : "OK", "note" : "HD" }
{ "_id" : ObjectId("4da31b8b5ba19e3c19345a66"), "USERID" : 4, "datekey" : "UGBYH", "balancekey" : "VOPRX" }
{ "_id" : ObjectId("4da31b8b5ba19e3c1a345a66"), "USERID" : 3, "userid" : "ZBWD", "password" : "FZAK", "key" : "QMEE" }
{ "_id" : ObjectId("4da31b8b5ba19e3c1b345a66"), "USERID" : 1, "accountname" : "GH", "weblink" : "MY", "note" : "QU" }
{ "_id" : ObjectId("4da31b8b5ba19e3c1c345a66"), "USERID" : 3, "userid" : "YZMW", "password" : "MVUR", "key" : "YSZC" }
{ "_id" : ObjectId("4da31b8b5ba19e3c1d345a66"), "USERID" : 4, "datekey" : "LIEWF", "balancekey" : "THXYR" }
{ "_id" : ObjectId("4da31b8b5ba19e3c1e345a66"), "USERID" : 4, "datekey" : "UIWOY", "balancekey" : "SKOKG" }
{ "_id" : ObjectId("4da31b8b5ba19e3c1f345a66"), "USERID" : 4, "datekey" : "POYKK", "balancekey" : "KZGDZ" }
{ "_id" : ObjectId("4da31b8b5ba19e3c20345a66"), "USERID" : 4, "datekey" : "LWNXW", "balancekey" : "VJXFC" }
{ "_id" : ObjectId("4da31b8b5ba19e3c23345a66"), "USERID" : 4, "datekey" : "IYMGO", "balancekey" : "RWBUE" }
{ "_id" : ObjectId("4da31b8b5ba19e3c24345a66"), "USERID" : 3, "userid" : "CJTH", "password" : "YQCL", "key" : "PCDB" }
{ "_id" : ObjectId("4da31b8b5ba19e3c25345a66"), "USERID" : 4, "datekey" : "OBOCN", "balancekey" : "XOHWA" }
{ "_id" : ObjectId("4da31b8b5ba19e3c26345a66"), "USERID" : 3, "userid" : "EHTQ", "password" : "KBXV", "key" : "YAMD" }
{ "_id" : ObjectId("4da31b8b5ba19e3c27345a66"), "USERID" : 5, "emailadress" : "VYSAHK" }
I need help writing a mapreduce functions to generate a string that would be like a csv structure.. so for example if i need data for userid = 4, the result would be
datekey,balancekey\n
BIBAK,MAIYM\n
QOTWH,SFEYQ\n
......
I am facing a problem doing the following .. Since each userid has different data, I need a way to go through those key/value pairs in a generic way .. So pretty much the question is how to loop through the objects parameters and get their values in order to emit them . and then in the reduce function i can concatenate them and add the \n.
Thanks
You can have csv values for each document using following code. There are two variants of map() function provided as example. First one is non-generic and helps understand the concept. While one, at the end, is generic. Try running both of them and you will understand the difference.
Map function - Not Generic
var map = function() {
var outputString = "";
if (this.datekey){
outputString += this.datekey;
}
outputString += "," ;
if (this.balancekey){
outputString += this.balancekey;
}
emit(this.USERID, {outputString:outputString});
};
Reduce function
var reduce = function(key,values){
overallOutputString = "";
values.forEach(function(i){
overallOutputString += i.outputString+"\n";
});
return { outputString:overallOutputString};
};
Performing the M/R operation
var result = db.items.mapReduce( map,
reduce,
{query:{USERID:{$exists:true}},
out: {replace:"csv_dump"}
});
Observing the output
db.csv_dump.find();
Map function - Generic
var map = function() {
var outputString = "";
for(var prop in this ) {
if (prop != "_id" && prop != "USERID" ){
outputString += this[prop]+",";
}
}
outputString = outputString.substring(0, outputString.length-1); // removing last comma
emit(this.USERID, {outputString:outputString});
};

Categories

Resources