MongoDB insert record issue - javascript

I have a Mongo DB structure which looks something like this :
db.users.find().pretty();
{
"_id" : ObjectId("52b42b148ffa91f7ebbe8ebc"),
"username" : "test",
"password" : "test",
"party" : [
"4988",
"5037"
],
"something" : [
"3571"
],
"ludilo" : [],
}
Im using express js in my app and this module for connecting to Mongo https://npmjs.org/package/mongodb ,
How can I insert one entry into "something" array for user with id that I get from session.
I tried something like this , but with no success
var collection = db.collection('users');
collection.find({'_id':new ObjectID(req.user.id)}).toArray(function(err, items) {
console.dir(items);
}).insert({"something":"1234"});

You can $push a value to an array with
db.users.update(
{ _id: ObjectId( "52b42b148ffa91f7ebbe8ebc" ) },
{ $push: { something: "1234" } }
)
or if you do not want any duplicates in your array you can use $addToSet
db.users.update(
{ _id: ObjectId( "52b42b148ffa91f7ebbe8ebc" ) },
{ $addToSet: { something: "1234" } }
)

You can try this code:
collection.find({_id: new ObjectID(req.user.id)}).toArray(function(err, items) {
var doc = items[0];
doc.something.push('1234');
collection.update({_id: doc._id}, {$set: {something: doc.something}}, {safe: true}, function() {
//your next actions
});
});
I run this code on my local machine and it seems to work fine

Related

Editing a value of an object in an array

I have this object:
{
"_id" : ObjectId("5a8d83d5d5048f1c9ae877a8"),
"websites" : [
"",
"",
""
],
"keys" : [
{
"_id" : ObjectId("5a8d83d5d5048f1c9ae877af"),
"name" : "Google",
"value" : ""
},
{
"_id" : ObjectId("5a8d83d5d5048f1c9ae877ae"),
"name" : "Built With",
"value" : ""
},
{
"_id" : ObjectId("5a8d83d5d5048f1c9ae877ad"),
"name" : "Check Host",
"value" : ""
},
{
"_id" : ObjectId("5a8d83d5d5048f1c9ae877ac"),
"name" : "Alexa",
"value" : ""
},
{
"_id" : ObjectId("5a8d83d5d5048f1c9ae877ab"),
"name" : "Facebook",
"value" : ""
},
{
"_id" : ObjectId("5a8d83d5d5048f1c9ae877aa"),
"name" : "Instagram",
"value" : ""
},
{
"_id" : ObjectId("5a8d83d5d5048f1c9ae877a9"),
"name" : "Moz",
"value" : ""
}
],
"username" : "admin#admin",
"isPremium" : false,
"accType" : "admin",
"hash" : "very long hash",
"salt" : "long salt",
}
Now. Using NodeExpress and Mongoose I need to be able to edit the value field inside of every object inside the keys array.
My GET operation is this:
// GET: /websites/:_id - show edit form
router.get('/keys/edit/:_id', isAdmin, function(req, res, next) {
// console.log('tada');
// console.log(req.params._id);
Account.findOne({ _id: req.user._id }, function(err, user) {
var selectedKey = findById(user.keys, req.params._id);
// var keys = user.keys.findOne(req.params._id);
console.log(selectedKey);
res.render('admin/edit', {
title: 'Edit websites',
user: req.user,
value: selectedKey.value,
});
});
});
How the app works is: The admin logs in. He sees all users and chooses which one he wants to modify, then admin sees all keys. I will attach screenshots to explain it more clearly.
Now. I think I know what I need to do, but I have no clue how to translate it to code.
I think I need to: Find the index of the array element, like in the GET request, update the value with the posted value. I think I need to find the index in the array.
But as I said I have no clue how to do it.
My POST looks like this right now:
// POST: /keys/edit/_id - save updates
router.post('/keys/edit/:_id', isAdmin, function(req, res, next) {
var p = req.params;
var b = req.body;
Account.findOne({ _id: req.user._id }, function(err, user) {
var selectedKey = findById(user.keys, req.params._id);
// console.log('Key value: ' + req.body.keyValue);
// console.log('Selected key: ' + selectedKey);
console.log('id:' + req.params._id);
if (err) {
console.log(err);
} else {
console.log(user);
user.keys.set(req.params._id, req.body.keyValue);
user.save(err => {
if (err) {
console.log(err);
} else {
console.log('all good');
}
res.redirect('/admin');
});
}
});
EDIT: So I was working on it for a while now and I figured out this. I am using the correct user, I am grabbing the keys array inside, but I don't know how to find the id of the object in the array, which (object) I need to edit.
There is a lot of nesting and this might cause some issues.
EDIT 2: I'm attacking my account model. Forgot about it earlier. Sorry.
var mongoose = require('mongoose');
var website = require('./website');
var plm = require('passport-local-mongoose');
var accountSchema = new mongoose.Schema({
isPremium: Boolean,
accType: String,
websites: [],
keys: [
{ name: String, value: String },
{ name: String, value: String },
{ name: String, value: String },
{ name: String, value: String },
{ name: String, value: String },
{ name: String, value: String },
{ name: String, value: String },
],
});
accountSchema.plugin(plm);
module.exports = mongoose.model('Account', accountSchema);
You can perform the update atomically using $positional operator.
You include the field (_id) from the keys to locate the index of element and replace the placeholder($) with the found index from query part in the update part to set the value in keys.
router.post('/keys/edit/:_id', isAdmin, function(req, res, next) {
var p = req.params;
var b = req.body;
Account.findOneAndUpdate(
{_id: req.user._id,'keys._id':req.params._id },
{$set:{'keys.$.value':req.body.keyValue}},
{new: true},
function(err, account) {}
);
The question isn't entirely clear to me what you're looking to do, but what I can infer is that you want to do the following:
You have some object that has an Array of keys that has the following shape:
{
"_id" : ObjectId("5a8d83d5d5048f1c9ae877af"),
"name" : "Google",
"value" : ""
}
Judging from your sample object, I'm inferring the schema is defined something like:
const mongoose = require('mongoose')
const definition = {
websites: [String],
keys: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Key'
}]
}
const accountSchema = new mongoose.Schema(definition)
module.exports = mongoose.model('Account', topicSchema)
By the looks of the route, you want to update/edit that object at the given index: keys[i]. If this is the case, then there is no need to manually traverse the array, update the model directly:
const Key = require('./path/to/models/Key')
router.post('/keys/edit/:id', async (req, res) => {
const { keyValue } = req.body
const conditions = { _id: req.params.id }
await Key.findOneAndUpdate({ id }, { value: keyValue }).exec()
res.status(201).json()
})
The item in the array will be updated when you query the parent model.

Meteor: How can i push items to users collections and create a list or array instead of replacing each item with the new one?

I'm trying to attach objects from another collection to the Meteor.user collection by a click event. I have a collection with a list of items called "categories" each category has a name field, its that name i want to push into the meteor.user.
Its supposed to work in a way that the user can push as many of these names as they want however its only accepting one entry, and when i click on another name, the new name replaces the old one, instead of being an array. how can i make it so that it can allow many entries?
client/users.js
Template.CategoriesMain.events({
'click .toggle-category': function(e){
//var id = $(e.target).attr('posts.name');
var id = $(e.target).parent().find("a").text();
console.log(id);
e.preventDefault();
Meteor.call('addingCategory', id, function(error, user){ console.log(id)});
}
});
server/users.js
Meteor.methods({
addingCategory: function(name) {
var cats = [{}];
cats.push(name);
console.log(Meteor.userId());
Meteor.users.update({
_id: Meteor.userId()
}, {
$set: {
name: name
}
});
}
});
and this is the user from db.user.find() as you can see with
"name" : "a-reece"
its clearly pushing the name but i cannot add more, i can only replace
{ "_id" : "4CHcZjSD4hCrqweGA", "createdAt" :
ISODate("2016-07-13T21:38:59.505Z"), "services" : { "password" : {
"bcrypt" :
"$2a$10$lKZtrYSMD4EGPj6eamgFDuPZ41Jw52DgivBly3lUYWbGDtfZBg1X." },
"resume" : { "loginTokens" : [ { "when" :
ISODate("2016-07-13T21:38:59.719Z"), "hashedToken" :
"BsqTGedB2FkmSPO3+5I31rOM2+MPtF97Zc9tRQ4pf8Y=" } ] } }, "emails" : [ {
"address" : "mun#les.com", "verified" : false } ], "roles" : [
"discoveror", "yes" ], "isAdmin" : true, "name" : "a-reece" }
how can i add more names instead of replacing?
EDIT
Meteor.methods({
addingCategory: function(name) {
//Meteor.users.update(Meteor.userId(), { $addToSet: { name: name} } );
console.log(Meteor.userId());
//Meteor.users.update(Meteor.userId(), { $set: { "categories": cats }} );
Meteor.users.update({
_id: Meteor.userId()
},
{
$unset: {
name: name
}
},
{
$addToSet: {
name: name
}
});
}
});
ANSWER
Template.CategoriesMain.events({
'click .toggle-category': function(e){
//var id = $(e.target).attr('posts.name');
var ob = $(e.target).parent().find("a").text();
var id = $.makeArray( ob );
console.log(id);
e.preventDefault();
Meteor.call('addingCategory', id, function(error, user){ console.log(id)});
}
});
You're currently doing:
Meteor.users.update({ _id: Meteor.userId() }, { $set: { name: name } });
You have two choices: $push or $addToSet:
Meteor.users.update({ _id: Meteor.userId() }, { $push: { name: name } });
or
Meteor.users.update({ _id: Meteor.userId() }, { $addToSet: { name: name } });
The former pushes onto an array, allowing duplicates, the latter avoids dupes.
You don't need:
var cats = [{}];
cats.push(name);

Update a specific field in a croncrete JSON object inside an JSON array (Mongoose)

I am trying to update a specific field in a concrete JSON object inside an JSON array with mongoose.
My MongoDB contains:
db.users.find({username:"xxx"})
{ "_id" : ObjectId("56cb877e73da764818ec5ded"),..., "githubtoken" : [ { "token" : "9e37axxx", "username" : "xxx", "_id" : ObjectId("572a7cfafe95dec51d9cbf2d") }, { "token" : "4529yyy", "username" : "yyy", "_id" : ObjectId("572a7d3cfe95dec51d9cbf2e") } ] }
And I want to get the JSON object that matches with "username" : "yyy"and "user._id" = "56cb877e73da764818ec5ded" and change its token to "token" : "4529zzz" with mongoose, like this:
{ "_id" : ObjectId("56cb877e73da764818ec5ded"),..., "githubtoken" : [ { "token" : "9e37axxx", "username" : "xxx", "_id" : ObjectId("572a7cfafe95dec51d9cbf2d") }, { "token" : "4529zzz", "username" : "yyy", "_id" : ObjectId("572a7d3cfe95dec51d9cbf2e") } ] }
The schema of db is:
var userSchema = new Schema({
username : { type: String, required: true },
...
githubtoken: [ { username: {type: String, required: false },
token: {type: String, required: false} }]
});
And update method:
userSchema.statics.updateuser = function updateuser (query, update, options) {
var promise = new Hope.Promise();
this.findAndUpdate(query, update, options,function(error, user) {
if (error) {
return promise.done(error, null);
}else {
return promise.done(null, user);
}
});
return promise;
};
And in my service with express.js:
query = {$and: [{_id: userid}, {githubtoken: {username:username, token:oldToken}} ]};
update = {$set : {githubtoken:{username:username, token:token}}};
options = { new: true};
User.updateuser(query,update,options).then(function (error,user){
if(error){
return promise.done(error,null);
}else{
}});
But it doesn't work, because remove all array of githubtokens and push only the new githubtoken, like this:
{ "_id" : ObjectId("56cb877e73da764818ec5ded"),..., "githubtoken" : { "token" : "4529zzz", "username" : "yyy", "_id" : ObjectId("572a7d3cfe95dec51d9cbf2e") } }
Any idea?
Thank you very much :D
You can use the $ - positional operator for the update:
db.collection('users').update({
"_id": ObjectId("56cb877e73da764818ec5ded"),
"githubtoken.username": "xxx"
}, {
$set: {
"githubtoken.$.username": username,
"githubtoken.$.token": token
}
});
And this should do the trick. More details on usage of $ - positional operator https://docs.mongodb.org/manual/reference/operator/update/positional/
Try changing the query like this:
var query = {
{
_id: new ObjectId(userid),
'githubtoken.username': username,
'githubtoken.token': oldToken
}
};
And update like this:
var update = {
$set: {
'githubtoken.$.username': username,
'githubtoken.$.token': token
}
};
I found the solution in this page:
query = {"githubtoken" :{$elemMatch: {"username": username}}};
update = {$set : {
"githubtoken.$.username": username,
"githubtoken.$.token": token
}};
Thanks for the help :D

Mongodb: Can't append to array using string field name

i am trying to push inside a subarray using $push but got a Mongo error, and not able to get through this after considerable search on google, and findOneAndUpdate didn't worked out so i used find and update separately
{ [MongoError: can't append to array using string field name: to]
name: 'MongoError',
err: 'can\'t append to array using string field name: to',
code: 13048,
n: 0,
lastOp: { _bsontype: 'Timestamp', low_: 2, high_: 1418993115 },
Schema:
var NetworkSchema = new Schema({
UserID: {
type: Schema.Types.ObjectId,
ref: 'User'
},
NetworkList: [{
type: Schema.Types.ObjectId,
ref: 'User'
}],
NetworkRequest: [{
from: [{
type:Schema.Types.ObjectId,
ref: 'User'
}],
to: [{
type: Schema.Types.ObjectId,
ref: 'User'
}]
}]
});
Document:
{
"UserID" : ObjectId("549416c9cbe0e42c1adb42b5"),
"_id" : ObjectId("549416c9cbe0e42c1adb42b6"),
"NetworkRequest" : [
{
"from" : [],
"to" : []
}
],
"NetworkList" : [],
"__v" : 0
}
Controller:
exports.update = function(req,res) {
var network = req.network;
var query={'UserID':req.body.UserID};
var update = {$push:{'NetworkRequest.to': req.body.FriendID}};
Network.find(query,function(err){
if (err) {
console.log(err);
return err;
} else {
}
});
Network.update(query,update,{upsert:true},function(err,user){
console.log(user);
if (err) {
console.log(err);
return err;
} else {
console.log('User'+user);
}
});
};
Everything #cbass said in his answer is correct, but since you don't have a unique identifier in your NetworkRequest element to target, you need to do it by position:
var query = {'UserID': req.body.UserID};
var update = {$push:{'NetworkRequest.0.to': req.body.FriendID}};
Test.update(query, update, {upsert: true}, function(err, result) { ... });
'NetworkRequest.0.to' identifies the to field of the first element of the NetworkRequest array.
Your query var query={'UserID':req.body.UserID}; identifies the document you want to edit. Then you need another query to identify which object in the NetworkRequest array that the UserID should be pushed into. Something like below:
var query = {
'UserID':req.body.UserID,
'NetworkRequest._id': ObjectId(someNetworkRequestId)
};
Then use this update query containing $ which is the index of the object in the nested array(NetworkRequest)
var update = {
$push:{
'NetworkRequest.$.to': req.body.FriendID
}
};

MongoDB, remove object from array

Doc:
{
_id: 5150a1199fac0e6910000002,
name: 'some name',
items: [{
id: 23,
name: 'item name 23'
},{
id: 24,
name: 'item name 24'
}]
}
Is there a way to pull a specific object from an array? I.E. how do I pull the entire item object with id 23 from the items array.
I have tried:
db.mycollection.update({'_id': ObjectId("5150a1199fac0e6910000002")}, {$pull: {id: 23}});
However I am pretty sure that I am not using 'pull' correctly. From what I understand pull will pull a field from an array but not an object.
Any ideas how to pull the entire object out of the array.
As a bonus I am trying to do this in mongoose/nodejs, as well not sure if this type of thing is in the mongoose API but I could not find it.
try..
db.mycollection.update(
{ '_id': ObjectId("5150a1199fac0e6910000002") },
{ $pull: { items: { id: 23 } } },
false, // Upsert
true, // Multi
);
I have a document like
I have to delete address from address array
After searching lots on internet I found the solution
Customer.findOneAndUpdate(query, { $pull: {address: addressId} }, (err, data) => {
if (err) {
return res.status(500).json({ error: 'error in deleting address' });
}
res.json(data);
});
my database:
{
"_id" : ObjectId("5806056dce046557874d3ab18"),
"data" : [
{ "id" : 1 },
{ "id" : 2 },
{ "id" : 3 }
]
}
my query:
db.getCollection('play_table').update({},{$pull:{"data":{"id":3}}},{multi:true}
output:
{
"_id" : ObjectId("5806056dce046557874d3ab18"),
"data" : [
{ "id" : 1 },
{ "id" : 2 }
]
}
You can try it also:
db.getCollection('docs').update({ },{'$pull':{ 'items':{'id': 3 }}},{multi:true})
For a single record in array:
db.getCollection('documents').update(
{ },
{'$pull':{ 'items':{'mobile': 1234567890 }}},
{new:true}
);
For a multiple records with same mobile number in array:
db.getCollection('documents').update(
{ },
{
$pull: {
items: { mobile: 1234567890 }
}
},
{ new:true, multi:true }
)
Use $pull to remove the data
return this.mobiledashboardModel
.update({"_id": args.dashboardId}, { $pull: {"viewData": { "_id": widgetId}}})
.exec()
.then(dashboardDoc => {
return {
result: dashboardDoc
}
});
Kishore Diyyana:
If you want to remove all elements including the key of the element attributes list.
Here is the example of mongoDB unset operator:
db.UM_PREAUTH_CASE.update(
{ 'Id' : 123}, { $unset: { dataElements: ""} } )
JSON Look like this:
{ "Id":123,"dataElements" : [ { "createdBy" : "Kishore Babu Diyyana", "createdByUserId" : 2020 }, { "createdBy" : "Diyyana Kishore", "createdByUserId" : 2021 } ] }

Categories

Resources