Merging two objects in node - node.js

This is my structure
[{
"date": "2019-01-10T18:30:00.000Z",
"time": "2019-01-11T04:37:49.587Z",
"abc_Info": {
"_id": "5c381da651f18d5040611eb2",
"abc": 2.5,
"guardian": "XYZ"
}
}]
What I want is
[{
"date": "2019-01-10T18:30:00.000Z",
"time": "2019-01-11T04:37:49.587Z",
"abc": 2.5,
"guardian": "XYZ"
}]
Code
this._model.find(params, (err, docs) => {
if (err) {
var response = this.errorResponse("error", 500, null);
res.send(response);
} else {
for (var i = 0; i < docs.length; i++) {
const abc= {
"date": docs[i].date,
"time": docs[i].time,
"abc_Info":docs[i].abc_Info //this is object, i couldn't select value separately from this object
}
if (docs[i].abc_Info != undefined) {
abcArray.push(abc);
}
}
res.send(abc);
}
});
I am trying to select values from object like "abc_Info":docs[i].abc_Info.abc but I couldn't do it, Its throwing error.
There are two way I can achieve this.
Selecting values directly from object and store in variable. That is throwing error for me
Merging date and time with abc_Info. I don't know how to do that

Chnage this.
const abc= {
"date": docs[i].date,
"time": docs[i].time,
"abc":docs[i].abc_Info.abc,
"guardian":docs[i].abc_Info.guardian
}

hope it will be helpful
var d=[{
"date": "2019-01-10T18:30:00.000Z",
"time": "2019-01-11T04:37:49.587Z",
"abc_Info": {
"_id": "5c381da651f18d5040611eb2",
"abc": 2.5,
"guardian": "XYZ"
}
}]
d[0]=Object.assign(d[0],d[0].abc_Info);
delete d[0]['abc_Info'];
delete d[0]['_id'];
console.log(d);

let x = {
"date": "2019-01-10T18:30:00.000Z",
"time": "2019-01-11T04:37:49.587Z",
}
let abc_Info = {
"_id": "5c381da651f18d5040611eb2",
"abc": 2.5,
"guardian": "XYZ"
}
// to concat
let z = {...x, ...abc_Info}
console.log(z)
You can use the above ES6 spread operator for the cause
Object.assign is quite better in performance so it'll be like this:
Or let z = Object.assign(x, abc_info);
In your code it should be like this:
const abc= {...{
"date": docs[i].date,
"time": docs[i].time,
}, ...docs[i].abc_Info}

Use Spread operator and also rather using for loop and push, use Array.prototype.map
let docs= [{
"date": "2019-01-10T18:30:00.000Z",
"time": "2019-01-11T04:37:49.587Z",
"abc_Info": {
"_id": "5c381da651f18d5040611eb2",
"abc": 2.5,
"guardian": "XYZ"
}
}]
let abcArray = docs.map(({date, time, abc_Info}) => {
delete abc_Info._id;
return {date, time, ...abc_Info }
});
console.log(abcArray)

Sorry Its my mistake. I should have declared object inside if statement. Its working now
if (docs[i].abc_Info != undefined) {
const abc= {
"date": docs[i].date,
"time": docs[i].time,
"abc_Info":docs[i].abc_Info
}
abcArray.push(abc);
}

Related

elasticsearch node.js API remove an object from an array on a document using painless script results in array Index Out of Bounds

I want to remove items (an object) from an array on a document in elasticsearch, however whenever I try and run my update script using painless, I receive an Array Index Out of Bounds exception.
I'm using the javascript elasticsearch npm package to search elasticsearch for the relevant documents which then returns me data like:
"_index": "centres",
"_type": "doc",
"_id": "51bc77d1-b514-4f4e-85fa-412def6829f5",
"_score": 1,
"_source": {
"id": "cbaa7daa-f1a2-4ac3-8d7c-fc981245d21c",
"name": "Five House",
"openDays": [
{
"title": "new open Day",
"endDate": "2022-03-22T00:00:00.000Z",
"id": "82be934b-eeb1-419c-96ed-a58808b30df7"
},
{
"title": "last open Day",
"endDate": "2020-12-24T00:00:00.000Z",
"id": "8cc339b9-d2f8-4252-b68a-ed0a49cbfabd"
}
]
}
I then want to go through and remove certain items from the openDays array. I've created an array of the items I want to remove, so for the above example:
[
{
id: '51bc77d1-b514-4f4e-85fa-412def6829f5',
indexes: [
{
"title": "last open Day",
"endDate": "2020-12-24T00:00:00.000Z",
"id": "8cc339b9-d2f8-4252-b68a-ed0a49cbfabd"
}
]
}
]
I'm then trying to run an update via the elasticsearch node client like this:
for (const centre of updates) {
if (centre.indexes.length) {
await Promise.all(centre.indexes.map(async (theIndex) => {
const updated = await client.update({
index: 'centres',
type: 'doc',
id: centre.id,
body: {
script: {
lang: 'painless',
source: "ctx._source.openDays.remove(ctx._source.openDays.indexOf('openDayID'))",
params: {
"openDayID": theIndex.id
}
}
}
}).catch((err) => {throw err;});
}))
.catch((err) => {throw err;});
await client.indices.refresh({ index: 'centres' }).catch((err) => { throw err;});
}
}
When I run this though, it returns a 400 with an "array_index_out_of_bounds_exception" error:
-> POST http://localhost:9200/centres/doc/51bc77d1-b514-4f4e-85fa-412def6829f5/_update
{
"script": {
"lang": "painless",
"source": "ctx._source.openDays.remove(ctx._source.openDays.indexOf(\u0027openDayID\u0027))",
"params": {
"openDayID": "8cc339b9-d2f8-4252-b68a-ed0a49cbfabd"
}
}
}
<- 400
{
"error": {
"root_cause": [
{
"type": "remote_transport_exception",
"reason": "[oSsa7mn][172.17.0.2:9300][indices:data/write/update[s]]"
}
],
"type": "illegal_argument_exception",
"reason": "failed to execute script",
"caused_by": {
"type": "script_exception",
"reason": "runtime error",
"script_stack": [],
"script": "ctx._source.openDays.remove(ctx._source.openDays.indexOf(\u0027openDayID\u0027))",
"lang": "painless",
"caused_by": {
"type": "array_index_out_of_bounds_exception",
"reason": null
}
}
},
"status": 400
}
I'm not quite sure where I'm going wrong with this. Am I using the indexOf painless script correctly? Does indexOf allow for the searching of properties on objects in arrays?
I stumbled across this question and answer: Elasticsearch: Get object index with Painless script
The body of the update script needs changing like so:
Promise.all(...
const inline = `
def openDayID = '${theIndex.id}';
def openDays = ctx._source.openDays;
def openDayIndex = -1;
for (int i = 0; i < openDays.length; i++)
{
if (openDays[i].id == openDayID)
{
openDayIndex = i;
}
}
if (openDayIndex != -1) {
ctx._source.openDays.remove(openDayIndex);
}
`;
const updated = await client.update({
index: 'centres',
type: 'doc',
id: centre.id,
body: {
script: {
lang: 'painless',
inline: inline,
},
}
}).catch((err) => {throw err;});
await client.indices.refresh({ index: 'centres' }).catch((err) => { throw err;});
})).catch(... //end of Promise.all
I am not au fait with painless scripting, so there are most likely better ways of writing this e.g. breaking once the index of the ID is found.
I have also had to move the refresh statement into the Promise.all since if you're trying to remove more than one item from the array of objects, you'll be changing the document and changing the index. There is probably a better way of dealing with this too.
'openDayID' should be params.openDayID
And use removeIf:
"ctx._source.openDays.removeIf(el -> (el.id == params.openDayID))"

how to write dynamic query in mongoose

i do not know if this has answer or not but i couldn't fix my issue .
Shift.updateOne({
$and: [{phone: number}, {statusSH: "open"}, {
'order.startTime': start,
'order.finishTime': finish
},{'order.orders.5.stat':"false"}]
},{'$set': {'order.orders.5.stat': "true"}},function (error,update) {
if (update){
}
});
this 'order.orders.5.stat' works fine . but i don't know how i can use dynamic index . like if i have a "var index" where should i add that to query . it seems if i 'order.orders.'+index+'.stat' i get error .
All helps will be appreciated. Thank You.
Edit :
doc should be like this
{
"_id": "5f52745e77abf55e80228379",
"phone": "09898989666",
"final": true,
"statusSH": "open",
"created_time": "1599239262",
"__v": 0
"order": {
"startTime": "139912292135",
"finishTime": "139912292240",
"orders": [
{
"_id": "5f52745e77abf55e8022837a",
"stat": "false",
},
{
"_id": "5f52745e77abf55e8022837b",
"stat": "false",
}
]
}
}
You need to use [] when you concat key of object,
var index = "5";
var number = "09898989666";
var start = "139912292135";
var finish = "139912292240";
Shift.updateOne({
$and: [
{ phone: number },
{ statusSH: "open" },
{
'order.startTime': start,
'order.finishTime': finish
},
{ ['order.orders.' + index + '.stat']: "false" } // change here
]
},
{
'$set': { ['order.orders.' + index + '.stat']: "true" } // change here
},
function(error, update) {
if (update) {
console.log(update)
}
});
x='order.orders.{}.stat'.format(index)
.... x:"false"

Multiple records for nested/embedded schema is not getting inserted in mongodb, nodejs

Hi I am new to nodejs and mongodb, I have json file with below structure,
I have defined one shipment schema with the "comments" section as nested schema
{
"buyerId": "B58",
"sellerId": "SL8",
"comments": {
"title": "title5",
"body": "body5",
"date": "12-07-2017"
}
}
I have defined one function like below
exports.post = function(req, res) {
const comments = []
var s = new shipment();
s.sellerId = req.body.sellerId;
s.buyerId = req.body.buyerId;
s.poId = req.body.poId;
s.comments.push({
title: req.body.comments.title,
body: req.body.comments.body,
date: req.body.comments.date
});
s.save(function(err) {
if (err) {
res.send(err);
}
console.log("added");
res.send({
message: 'shipment Created !'
})
})
}
The above 'post' function will work properly when I have only one "comments" section, I mean the data gets properly
inserted into the mongodb as shown below
{
"_id": ObjectId("59689bc59058dbc812000002"),
"buyerId": "B58",
"sellerId": "SL8",
"comments": [{
"title": "title5",
"body": "body5",
"date": ISODate("2017-12-06T18:30:00Z"),
"_id": ObjectId("59689bc59058dbc812000003")
}],
"__v": 0
}
but when I have multiple "comments" section as shown below,
{
"buyerId": "B58",
"sellerId": "SL8",
"comments": [{
"title": "title5",
"body": "body5",
"date": "12-07-2017"
},
{
"title": "title8",
"body": "body7",
"date": "12-07-2017"
}
]
}
then no comments section gets inserted into the mongodb as shown below.
{
"_id": ObjectId("5968c04d4c02336800000002"),
"buyerId": "B57",
"sellerId": "SL7",
"comments": [{
"_id": ObjectId("5968c04d4c02336800000003")
}],
"__v": 0
}
what changes should I do in the function to get all the comments section being inserted into the mongodb properly ?
Instead of assigning value of every property, make instance and pass body directly into it.
const s = new shipment(req.body)
And then when you send data to the request, send in the following format
{ "buyerId": "B58", "sellerId": "SL8", "comments": [{ "title": "title5", "body": "body5", "date": "12-07-2017" }, { "title": "title8", "body": "body7", "date": "12-07-2017" } ] }
I tried like below and it worked.
for( var i = 0; i < req.body.comments.length; i++){
s.comments.push(
{ title: req.body.comments[i].title,
body : req.body.comments[i].body,
date : req.body.comments[i].date });
}
originally comments is an array in the second example comments is an array.
your function
s.comments.push({
title: req.body.comments.title,
body: req.body.comments.body,
date: req.body.comments.date
})
will only work if comments is an object. Put that in a for loop to make it work with arrays like so
for( var i = 0; i < req.body.comments.length; i++){
s.comments.push({
title: req.body.comments[i].title,
body: req.body.comments[i].body,
date: req.body.comments[i].date
})
}

Return Array from Embedded document

I have a data like in mongodb collection name property.
{
"_id": "593a3d828e2ef100d1496e77",
"feature_type": "house",
"features": [
{
"name": "h1"
},
{
"name": "h2"
}
]
}
I want only
[
{
"name": "h1"
},
{
"name": "h2"
}
]
as result i tried this by
req.db.collection('FeatureSettings').findOne({feature_type: req.params.feature_type}, {features: 1});
this give
{
"_id": "593a3d828e2ef100d1496e77",
"features": [
{
"name": "Hotel"
},
{
"name": "Apartment"
}
]
}
what can i do to get result as given above.
You have to exclude the _id from your projection like here:
req.db.collection('FeatureSettings').findOne({feature_type: req.params.feature_type}, {features: 1, _id:0});
Assuming you're using something like mongoose that returns promises, you could use the result of the query
return req.db.collection('FeatureSettings')
.findOne({feature_type: req.params.feature_type}, {features: 1})
.then((result) => {
return result.features;
});
You can try this to return only features array values.
req.db.collection('FeatureSettings')
.findOne({feature_type: req.params.feature_type}, {features:1, _id:0}).features;
OR
// if you use mongoose can use
return req.db.collection('FeatureSettings')
.findOne({feature_type: req.params.feature_type}, {features:1, _id:0})
.exec()
.then((result) => {
return result.features;
});

Node + Mongodb. $pull not working?

I am using Node.js and MongoDB and I'm trying to setup a DELETE route. In the function responsible for handling the delete I am using Mongo's "$pull" operator. I've looked at a couple of examples now and I don't know what I am doing wrong.
Here's a sample of how the database documents are setup
{
"_id": {
"$oid": "123abc"
},
"sleepData": [
{
"date": "03/28/2016",
"hour": "11",
"minute": "11",
"meridiem": "PM",
"feeling": "7"
},
{
"date": "03/29/2016",
"hour": "3",
"minute": "41",
"meridiem": "PM",
"feeling": "1"
},
{
"date": "03/30/2016",
"hour": "1",
"minute": "29",
"meridiem": "AM",
"feeling": "5"
},
{
"date": "03/30/2016",
"hour": "1",
"minute": "38",
"meridiem": "AM",
"feeling": "4"
},
]
}
*Note the near-duplicate data, thus the reason why my $pull query is so specific.
Here is my function for the route
module.exports.DELETE = function(req, res) {
var sleepDataToDelete = {
date: req.query.date,
hour: req.query.hour,
minute: req.query.minute,
meridiem: req.query.meridiem,
feeling: req.query.feeling
};
// next code block is what this console prints out
console.log("Deleting req.query:\n", sleepDataToDelete);
var sleepObjectId = req.query.sleepObjectId;
var sleepDataCollection = db.get().collection('sleepData');
sleepDataCollection.update(
{
_id: sleepObjectId
},
{
$pull: {
sleepData: {
date: sleepDataToDelete.date,
hour: sleepDataToDelete.hour,
minute: sleepDataToDelete.minute,
meridiem: sleepDataToDelete.meridiem,
feeling: sleepDataToDelete.feeling
}
}
},
function(err, result) {
if(err) {
console.log("err", err);
return res.status(400).end();
} else {
console.log("Count: ", result.result.n);
console.log("Deleted! :) ");
return res.status(200).end();
}
}
);
};
This is what the console.log("Deleting req.query:\n", sleepDataToDelete); prints out, which also matches the third index in the sleepData array.
Deleting req.query:
{
date: '03/30/2016',
hour: '1',
minute: '29',
meridiem: 'AM',
feeling: '5'
}
I have even tried putting the json field names in double/single quotes, but that didn't work either. The number of objects modified is 0. I have also tried reducing the "$pull {...}" query to just "date" instead of having "date", "hour", "minute", "meridiem", and "feeling." This still results in 0 modified items from the print statement.
As #BlakesSeven pointed out, I was not passing in an ObjectId in my query. So, credit goes to him. Needless to say, this solved my issue.

Resources