mongodb updating only specific subelements - javascript

my db structure looks like:
{
"_id" : ObjectId("51e66873f6a6600436000001")
,"email" : "asd#asd.de",
,"attribute_group_a" : {
"attribute_a" : ""
,"attribute_b" : ""
,"attribute_c" : ""
,"attribute_d" : ""
},
,"attribute_group_b" : {
"attribute_subgroup_b_a" : {
"attribute_a" : ""
,"attribute_b" : ""
,"attribute_c" : ""
,"attribute_d" : ""
}
,"attribute_subgroup_b_b" : {
"attribute_a" : ""
,"attribute_b" : ""
,"attribute_c" : ""
,"attribute_d" : ""
}
}
}
so lets say i want to update att_subgrp_b_a:
exports.updateProfil = function(req, res, item, callback) {
var email = req.session.email;
db.collection('profiles', function(err, collection) {
collection.update({"email": email},{$set: item}, function(err, result)
the var "item" looks like:
{
attribute_group_b:
{
attribute_subgroupgroup_b_a:
{
att_a: "xy"
,att_b: "xy"
}
}
}
when i now update the file => it deletes everything in attr_group_b and replaces it with "item"
that means attr_subgrp_b_b is totally gone and all other attributes (of attr_subgrp_b_a) that weren't updated
i want that it looks for the attributes in "item", replaces them into db letting all other obj untouched

Try the query below
var email='emailid';
var item='whichuwanttoupdate';
collection.update(
{"email": email},
{$set:{'attribute_group_b.attribute_subgroup_b_a':item}},
function(err,result){
});

Related

How to access JSON string containing null value in Javascript

I have this JSON I retrieve from an API that contains null values. How do I better traverse the JSON and abstract the functionality?
const colletionjson =
{ "collections":
[ { "title" : "Home page"
, "description" : null
, "image" : null
}
, { "title" : "Products"
, "description" : "Products"
, "image" : { "src": "https:www.example.com" }
, "products_count" : 3
}
]
}
$.each(collectionjson, function (key, value) {
$.each(value, function (key, value) {
var collectionTitle = value.title;
var collectionDescription = value.description;
if (value == "image" && $.isArray(value)) {
var collectionImage = value.image.src;
} else {
var collectionImage = "";
}
});
});
// Do something with the data
you can now use Optional chaining (?.) with ECMAScript 2020
sample code
const colletionjson = // just a name
{ collections:
[ { title : 'Home page'
, description : null
, image : null
}
, { title : 'Products'
, description : 'Products'
, image : { src : 'https:www.example.com' }
, products_count : 3
}
]
}
colletionjson.collections.forEach((collection, i) =>
{
let collectionTitle = collection.title
, collectionDescription = collection.description || ''
, collectionImage = collection.image?.src || ''
;
console.log (`index: ${i}, title: ${collectionTitle}, description: ${collectionDescription}, image: ${collectionImage}` )
})
if (colletionjson.collections && Array.isArray(colletionjson.collections)) {
colletionjson.collections.forEach(value => {
const collectionTitle = value.title;
const collectionDescription = value.description;
let collectionImage = '';
if (value.image && value.image.src) {
collectionImage = value.image.src;
// do something with this value
}
})
}

How to update all nested documents of an array in a selected document in mongoose?

In a situation I need to update a field of all documents nested in an array in Mongoose model.
I add a new nested document of uploaded image to Users collection and I need to set "is_available" of all previous documents to be false and only "is_available" field of newly inserted document to be true.
All I searched and found was about updating a nested document with specific id or filter. but I didn't find a way to update a specific field of all nested documents of an array in a Model.
My Model:
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var UsersSchema = new Schema({
name: { type: String, default: "" },
lastname: { type: String, default: "" },
images: [{
dir: { type: String },
is_available: { type: Boolean }
}]
});
var Users = mongoose.model("Users", UsersSchema, "users");
module.exports = Users;
Actual result:
{
"_id" : ObjectId("5ce950aa4sw435ty503ab83b"),
"name" : "Sina",
"image" : [
{
"_id" : ObjectId("5cf4dd3da6b4gb6bcf9c6dc1"),
"dir" : "profiledirectory/804eafeaf8acc40a3d6.jpg",
"is_available" : true
},
{
"_id" : ObjectId("5cf4fffs2419316bddffgg82"),
"dir" : "profiledirectory/d85b01ac40fa6b1a7c1.jpg",
"is_available" : true
},
{
"_id" : ObjectId("5cf4ff334fhd316bef2fdt40"),
"dir" : "profiledirectory/512d9d19da7a4322b37.jpg",
"is_available" : true
}
]
}
Expected Result:
{
"_id" : ObjectId("5ce950aa4sw435ty503ab83b"),
"name" : "Sina",
"image" : [
{
"_id" : ObjectId("5cf4dd3da6b4gb6bcf9c6dc1"),
"dir" : "profiledirectory/804eafeaf8acc40a3d6.jpg",
"is_available" : false
},
{
"_id" : ObjectId("5cf4fffs2419316bddffgg82"),
"dir" : "profiledirectory/d85b01ac40fa6b1a7c1.jpg",
"is_available" : false
},
{
"_id" : ObjectId("5cf4ff334fhd316bef2fdt40"),
"dir" : "profiledirectory/512d9d19da7a4322b37.jpg",
"is_available" : true
}
]
}
Code Snippet:
let updateQuery = {
$set: { 'image.$.is_available': false },
$push: {
image: [
{
dir: "profiledirectory/558bb6938ecd54bde556af122a4.jpg",
is_available: true
}
]
}
}
let findQuery = { _id: req.body.user_id }
Users.findOneAndUpdate(findQuery,
updateQuery, function (err, doc) {
if (err) {
res.send(err.message)
} else {
res.send('successful')
}
})
According to what you've mentioned, you keep adding objects to image field dynamically, and each time you add the new object, the existing objects should be overridden with is_available:false
eventObject.find(query).lean().exec(function (err, response) {
if (err) {
logger.error(err);
return reject(err.message)
}
// Assuming there will be only one record based on the query you make
if(response.length>0){
response[0].images = response.images.map((image)=>{
image.is_available = false
return image
})
// Now append your new image to the modified response
response[0].images.push(newimage)// this should be the newImage object
// Now use findOneAndUpdate to update the existing doc by querying with id or according to your usecase
eventObject.findOneAndUpdate(query, response[0], { upsert: true }, (err, data) => {
if (err) {
return reject(err)
}
logger.info(data);
return resolve(newData);
})
}
})
So the basic approach is,
Get the doc from the DB
Update the content of the doc
Add the new data
update the record with updated data.
after you uploaded file , you have to find user
// after upload image
User.findOne({_id:req.user._id}).lean().exec((err,user)=>{
if(!err && user){
// setting all previous images to false
user.image.forEach(image=>{
image.is_available=false;
});
// now pushing new uploded item to image array
let newImage={"dir" : "path of uploaded item here" , "is_available" : true};
user.image.push(newImage);
user.save((err,updated)=>{
if(!err && updated){
return res.status(200).json({status:"success",message:"User updated"});
}
});
}
});

MongoDB Check if a document/record exists

Im trying to use .find({}) with mongogb and unfortunately its not giving me the response I was expecting, I'm unsure how to check if the document exists or not? What I'm trying to do is say:
If a document does exist then do something.. IE send a response back
but If a document doesn't exist then create the document,
unfortunately I know that a document doesnt exist yet it must be picking up the wrong thing with 'if (docs)' but then when I change it to something else then it always creates records!?
The code:
addRefund : (refundCalc, callback) => {
order_number = refundCalc.refundDetails.customer_details.order.order_number;
dbconnect.createConnection()
refund.find({order_number: order_number}, (err, docs) => {
if (docs) {
console.log('docss!!!!!!!!!!!!!' + JSON.stringify(docs));
console.log('calling within error!!!!!!')
let notStored = {"refundDocStored" : "False"}
callback(notStored)
dbconnect.closeConnection();
}
else {
refund.create(refundCalc).then((refunddoc) => {
let filestored = {"refundDocStored" : "True"}
dbconnect.closeConnection();
callback(filestored)
}).catch((err)=> {
console.log(err);
dbconnect.closeConnection();
})
}
})
},
the schema:
const refundSchema = new Schema({
domain : { type: String},
refundDetails : {
customer_details : [],
refund : {
shipping : {
amount : { type: Number},
tax : {type : Number},
maximum_refundable : {type : Number}
},
refund_line_items: [],
transactions: []
}
}
});
The orders are stored within the refundDetails like this:
"refundDetails":{"customer_details":{"order":{"order_number":1021
It simply doesnt seem to work for me! if a document exists i cant seem to actually prove that it does?
Any help would be great, thanks!
You are using the wrong search query. You are searching for order_number which is a property of an object inside another object. You have to reference the order_number full path in your query i.e {"refundCalc.refundDetails.customer_details.order.order_number" : order_number}
addRefund : (refundCalc, callback) => {
order_number = refundCalc.refundDetails.customer_details.order.order_number;
dbconnect.createConnection()
refund.find({"refundCalc.refundDetails.customer_details.order.order_number": order_number}, (err, docs) => {
if (docs) {
console.log('docss!!!!!!!!!!!!!' + JSON.stringify(docs));
console.log('calling within error!!!!!!')
let notStored = {"refundDocStored" : "False"}
callback(notStored)
dbconnect.closeConnection();
}
else {
refund.create(refundCalc).then((refunddoc) => {
let filestored = {"refundDocStored" : "True"}
dbconnect.closeConnection();
callback(filestored)
}).catch((err)=> {
console.log(err);
dbconnect.closeConnection();
})
}
})
},

Firebase v3 Query by Grandchild

When registering new email/password type users, I need to make user that the displayName that they enter does not already exist in my Realtime Database before calling .createUserWithEmailAndPassword. So I need a query. I need to get a list of all displayName's in my users branch. I am confused as to how to gather this for each user which is denoted by each users auth.uid.
What would the retrieval look like? I am thinking something like:
firebase.database().ref('users/' + allUserIds).equalTo('Joe');
but I know that allUserIds is not valid. Can someone help me with this?
{
"users" : {
"6mJb9vtpbDelyyjirKEf6sSEj8h1" : {
"name" : "asdfs#asdf.com",
"provider" : "password",
"displayName" : "Joe"
},
"T7D7qEOPPHXjKSzglKheGJDQNkE3" : {
"name" : "gfdsdf#hlkjh.com",
"provider" : "password",
"displayName" : "Jane"
},
"kTG9R0V4aXYsogQfgF633KFYtzV2" : {
"name" : "Andre3000",
"provider" : "google.com",
"displayName" : "Andre"
}
}
}
You'd use Firebase queries for that:
var users = firebase.database().ref('users');
var joes = users.orderByChild('displayName').equalTo('Joe');
joes.once('value', function(snapshot) {
console.log('A Joe does '+(snapshot.exists()?'':'not ')+' exist')
});
Don't forget to define an index on users:
{
"rules": {
"users": {
".indexOn": "displayName"
}
}
}
Just thought I'd share my somewhat fleshed out solution. Call with myApp.displayNameExists('Joe').
var myApp = (function() {
var pub = {};
pub.displayNameExists = function(name) {
var users = firebase.database().ref('users');
var duplicate = users.orderByChild('displayName').equalTo(name);
duplicate.once('value').then(function(snap) {
if (snap.val()) {
console.log('found. ask for new display name');
} else {
console.log('name unique. ok to write this user to db');
}
}, function(error) {
// The Promise was rejected.
console.error(error);
});
}
//API
return pub;
}());

how to nest mongodb queries through node.js?

I am having a collection of users of the type -
{
"_id" : ObjectId("56f60e4eea8af4670408483e"),
"twitterHandle" : "shrutip",
"firstName" : "Shruti",
"lastName" : "Patil",
"emailID" : "shrutip#gmail.com",
"password" : "91382451347786e9b8f2f3817b27a2adfec1880c",
"phoneNumber" : "98739458789",
"location" : "San Jose",
"birthYear" : 1992,
"birthMonth" : 1,
"birthDay" : 10,
"followers" : [
"abhayp",
"anupd",
"lubdhal",
"poojag",
"prashantb",
"pratiksanglikar",
"shaileshyedge",
"shrutip"
],
"following" : [
"abhinavk",
"anupd",
"hiteshn",
"lubdhal",
"omkarn",
"poojag",
"pratiksanglikar",
"shaileshyedge",
"shrutip"
],
"tweets" : [
{
"tweet_id" : "3c50e98cf0c2298f40f98a013cd4a18a1443b7ac",
"tweet_text" : "At BJP youth wing meet, seniors worry over #JNU controversy, and not #RamTemple.",
"createdOn" : ISODate("2016-03-07T23:37:27Z"),
"tags" : [
"JNU",
"RamTemple"
]
}
]
}
I want to create feed (all tweets of the users the given user is following in ascending order of date) for any given user. I got the list of users which the given user is following, but I need to find the tweets of the found users. How do I do it in node.js? How to nest these queries?
What I've done so far is listed below -
var cursor = MongoDB.collection("users").find({
"twitterHandle": twitterHandle
});
cursor.each(function(err, doc) {
assert.equal(err, null);
if (doc != null) {
var followingCursor = MongoDB.collection("users").find( { twitterHandle: { $in: doc.following } } );
followingCursor.each(function (err, following) {
if(following != null) {
feed.push(following.tweets);
}
});
promise.resolve(feed);
}
});
But somehow, the promise gets resolved before the second query executes.
How do I ensure that all the iterations of followingCursor.each are executed before I return the promise?
Eventually I found out the answer myself.
if (doc != null) {
var followingCursor = MongoDB.collection("users").find( { twitterHandle: { $in: doc.following } } );
followingCursor.each(function (err, following) {
if(following != null) {
feed.push(following.tweets);
}
});
promise.resolve(feed);
}
In the above code, promise should be resolved if the following != null condition fails.
Apparently MongoDB driver returns null when the values in cursor end. The correct code is as following -
if (doc != null) {
var followingCursor = MongoDB.collection("users").find( { twitterHandle: { $in: doc.following } } );
followingCursor.each(function (err, following) {
if(following != null) {
feed = feed.concat(following.tweets);
} else {
promise.resolve(feed);
}
});
}

Categories