updating multiple objects in an array from multi object req.body - javascript

Ok, I have this collection:
{
"_id" : ObjectId("59baa8af86e5df3984674639"),
"centralPath" : "C:\\Users\\konrad.sobon\\OneDrive - HOK\\GoogleDrive\\Work\\DynamoWork\\142_SeatManifestGenerator\\RVT2018\\CBUEC_HOK_IN-central.rvt",
"totalFamilies" : 31,
"unusedFamilies" : 18,
"oversizedFamilies" : 0,
"inPlaceFamilies" : 0,
"createdBy" : "konrad.sobon",
"createdOn" : ISODate("2017-09-14T20:19:09.525Z"),
"families" : [
{
"name" : "Spot Elevation - Target Filled_HOK_I",
"size" : "1.2Mb",
"sizeValue" : 1200000,
"instances" : 0,
"elementId" : 6158,
"isFailingChecks" : true,
"isDeleted" : false,
"_id" : ObjectId("59bae43d2720015998392905"),
"tasks" : [],
"parametersCount" : 0,
"nestedFamilyCount" : 1,
"voidCount" : 0,
"refPlaneCount" : 2,
"arrayCount" : 0
},
{
"name" : "Section Head - Filled_HOK_I",
"size" : "140kb",
"sizeValue" : 145760,
"instances" : 0,
"elementId" : 8762,
"isFailingChecks" : true,
"isDeleted" : false,
"_id" : ObjectId("59bae43d2720015998392904"),
"tasks" : [],
"parametersCount" : 0,
"nestedFamilyCount" : 1,
"voidCount" : 0,
"refPlaneCount" : 3,
"arrayCount" : 0
},
{
"name" : "Railing Tag_HOK_I",
"size" : "244kb",
"sizeValue" : 249856,
"instances" : 0,
"elementId" : 12426,
"isFailingChecks" : true,
"isDeleted" : false,
"_id" : ObjectId("59bae43d2720015998392903"),
"tasks" : [],
"parametersCount" : 3,
"nestedFamilyCount" : 1,
"voidCount" : 0,
"refPlaneCount" : 2,
"arrayCount" : 0
},
{
"name" : "Fixed",
"size" : "316kb",
"sizeValue" : 323584,
"instances" : 0,
"elementId" : 3499132,
"isFailingChecks" : true,
"isDeleted" : false,
"_id" : ObjectId("59bae43d27200159983928e7"),
"tasks" : [],
"parametersCount" : 4,
"nestedFamilyCount" : 2,
"voidCount" : 0,
"refPlaneCount" : 18,
"arrayCount" : 0
}
],
"__v" : 0
}
What I am trying to do is send a request to update certain "families" in that collection. I have an array of these Family objects looking like this:
{"key": [
{
"name" : "New Spot Elevation - Target Filled_HOK_I",
"size" : "1.2Mb",
"sizeValue" : 1200000,
"instances" : 0,
"elementId" : 6158,
"isFailingChecks" : true,
"isDeleted" : false,
"Id" : "59bae43d2720015998392905",
"tasks" : [],
"parametersCount" : 0,
"nestedFamilyCount" : 1,
"voidCount" : 0,
"refPlaneCount" : 2,
"arrayCount" : 0
},
{
"name" : "New Section Head - Filled_HOK_I",
"size" : "140kb",
"sizeValue" : 145760,
"instances" : 0,
"elementId" : 8762,
"isFailingChecks" : true,
"isDeleted" : false,
"Id" : "59bae43d2720015998392904",
"tasks" : [],
"parametersCount" : 0,
"nestedFamilyCount" : 1,
"voidCount" : 0,
"refPlaneCount" : 3,
"arrayCount" : 0
}
]}
Now, I need to be able to find and update each of the specified families. I thought that i can just iterate over the incoming array (I am sending it in a req.body), and then make an array of Ids that would need to be updated so i can use the $in operator in mongo. After that, i thought that I can use the id, to retrieve the properties that I am interested and just use $set to get them updated. My attempt here:
module.exports.updateMultipleFamilies = function (req, res) {
var id = req.params.id;
var famIds = []; // [ObjectId]
var newFamilies = {}; // {"id_string" : family}
for(var key in req.body) {
if(req.body.hasOwnProperty(key)){
for(var i = 0; i < req.body[key].length; i++){
var family = req.body[key][i];
newFamilies[family.Id] = family;
famIds.push(mongoose.Types.ObjectId(family.Id));
}
}
}
Families
.updateMany(
{_id: id, 'families._id': {$in: famIds}},
{$set: {'name': newFamilies["current_document_id_help"].name}}, function(err, result){
if(err) {
res
.status(400)
.json(err);
} else {
res
.status(202)
.json(result);
}
}
)
};
Edit:
So i tried a different approach with the bulkWrite call. It doesn't give me errors but it also doesn't update anything. Any ideas why?
module.exports.updateMultipleFamilies1 = function (req, res) {
var id = req.params.id;
var bulkOps = [];
for(var key in req.body) {
if(req.body.hasOwnProperty(key)){
bulkOps = req.body[key].map(function(item){
return {
'updateOne': {
'filter': {'_id': id, 'families._id': mongoose.Types.ObjectId(item.Id)},
'update': {'$set': {'families.$.name': item.name}},
'upsert': false
}
}
})
}
}
Families.collection
.bulkWrite(
bulkOps,
{'ordered': true, w:1}, function(err, result){
if(err) {
res
.status(400)
.json(err);
} else {
res
.status(202)
.json(result);
}
})
};

you need to take the families array , change the code in the app and then update the families array again.
or you can try do {$set:{'families.$.name':newFamilies["current_document_id_help"].name}
}
but im not sure if that wont update all you families
first solution:
var id = req.params.id;
yourCollation.findById(id,function(err, doc){
if(req.body.key && req.body.key.constructor === Array){
for(var i = 0; i < req.body.key.length; i++){
for(var x in doc.families ){
if(family.id === doc.families[x].id){
doc.families[x] = family;
}
}
}
}
doc.save()
})

Related

Find and remove nested level

I want to find and remove the value, where my id is "5cc6d9737760963ea07de411"
my data:
[
{
"products" : [ {
"id" : "5cc6d9737760963ea07de411",
"quantity" : 1,
"totalPrice" : 100,
},
{
"id" : "5cc6d9737760963ea07de412",
"quantity" : 2,
"totalPrice" : 200,
}
],
"isCompleted" : false,
"_id" : "5cc7e4096d7c2c1f03570a2f"
},
{
"products" : [{
"id" : "5cc6d9737760963ea07de414",
"quantity" : 1,
"totalPrice" : 100,
},
{
"id" : "5cc6d9737760963ea07de4133",
"quantity" : 2,
"totalPrice" : 200,
}
],
"isCompleted" : false,
"_id" : "5cc7e4096d7c2c1f03570a2f"
}
]
i tried:
Schema.findOneAndUpdate({"products.id": "5cc6d9737760963ea07de411"},
{ $pull: {"products.$.id": "5cc6d9737760963ea07de411" })
but it's not working.
Now you don't need to use .dot notation. Instead you need to use "absolute" object structures:
Schema.findOneAndUpdate(
{ "products.id": "5cc6d9737760963ea07de411" },
{ "$pull": { "products": { "id": "5cc6d9737760963ea07de411" }}}
)

JSON parse eror from query SELECT Mongoose in NodeJS

I have data from schema "notification" in Mongoose like this :
{
"_id" : ObjectId("5c141ef2a7c50a773661772d"),
"title" : "MY POny",
"message" : "message POny",
"token" : "dHvoi4DQAMw:APA91bFGwBjDRCaOFaodRlgrVLKPLsXRlCymce5an_POCC5WlluOCbCbHWmXr2BvPqifdirxcSOwGJky-BBSyvDqj0ojwSrqDKrBHB0KwyNcZm2l-YHBpVkBlIOwfoiQkZsXZlFOxVj6",
"os" : "ANDROID",
"dateCreated" : ISODate("2018-12-14T14:21:51.834Z"),
"dateUpdated" : ISODate("2018-12-14T14:21:51.834Z"),
"deleted" : false,
"payload" : {
"type" : "PROMO",
"data" : {
"message" : "blabalbla…",
"url" : "https://www.pony.com/pony.png",
"datetime" : "2018-02-06 17:00"
}
},
"mobile" : "123456789101",
"id" : 171,
"__v" : 0,
"response" : {
"multicast_id" : 4.83405561199415e+18,
"success" : 1,
"failure" : 0,
"canonical_ids" : 0,
"results" : [
{
"message_id" : "0:1544822514686455%29669a5329669a53"
}
]
}
}
i have query like this
let getListNotif = await NOTIF.find({mobile : mobile, 'payload.type' : {$ne : 'TRANSACTION'}}).sort({'dateCreated': -1}).limit(limit)
i want to output like this :
let notifShow ={
mobile : getListNotif.mobile,
payload : getListNotif.payload
}
why error json parse in node js when i want send like this :
res.status(200).json(notifShow)
fix done
try {
let getListNotif = await NOTIF.find({'token' : token, 'payload.type' : {$ne : 'TRANSACTION'}}).sort({'dateCreated': -1}).limit(limit)
let array = []
let notifShow = {}
for(let i = 0; i < getListNotif.length; i++){
notifShow = {
mobile : getListNotif[i].mobile,
payload : getListNotif[i].payload
}
array.push(notifShow)
}
res.status(200).json(array)
} catch (error) {
logger.error(error.message)
res.status(422).json(Object.assign({message: error.message}, params))
}

Mongoose (MongoDB) - Error: Can't use $each with Number

I've to push a given array of Number values into a selected Document inside my MongoDB database.
The Document that I'm going to update as the following structure:
{
"_id" : {
"id" : 17,
"type" : "f"
},
"__v" : 0,
"created_at" : ISODate("2017-03-22T11:16:21.403Z"),
"token" : {
"expDate" : ISODate("2017-12-31T00:00:00Z"),
"token" : "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6ImFsYWRpbkBjb25zb3J6aW9jZXIuaXQiLCJleHAiOjE1MTQ2Nzg0MDB9.QvbT146bA_KH5XA7MH8ASXm9cr3sPZChJ3prYyDireI"
},
"updated_at" : ISODate("2017-07-24T09:42:33.741Z"),
"plots" : {
"idPlot" : [
23570,
23475
]
},
"machines" : [
{
"idPlotBind" : 1,
"ip" : "",
"mac" : "18-5F-00-4A-FE-F4",
"irrId" : 31,
"_id" : ObjectId("59084f527d634d301338aac6"),
"addr" : "pialadin.ddns.net"
},
{
"idPlotBind" : null,
"ip" : "",
"mac" : "12-01-02-FE-AB-B2",
"irrId" : 35,
"_id" : ObjectId("59084f7d7d634d301338aac7")
}
]
}
I'm using the Mongoose library for JS, and the accused query is this one:
userSchema.findOneAndUpdate({$and:[{ '_id.id': resData.PlotRows.IdUser}, {'_id.type': 'f'}]},{$addToSet:{'plots.$.idPlot': {$each: plotData}}}, {upsert: false}, function(err, usr){
if(err){
console.log(err);
return;
}
});
But when I try to execute it, gives me back:
Error: Can't use $each with Number

$multiply only supports numeric types, not array

I am trying to use the $multiply operator in MongoDB.
STEP 1
db.message1064sd_00011_3744.aggregate([
{$project : {
"prices.00026" : 1,
priceReal : {
price : "$prices.00026",
}
}},
{ $match : { "priceReal.price" : {$gt : 30 } } },
{ $limit : 1 }
])
I am getting the results
{
"result" : [
{
"_id" : "54884_00011_001",
"prices" : {
"00026" : 34.43
},
"priceReal" : {
"price" : 34.43
}
}
],
"ok" : 1
}
STEP 2
But, when I use $multiply, I get
$multiply only supports numeric types, not array
db.message1064sd_00011_3744.aggregate([
{$project : {
"prices.00026" : 1,
priceReal : {
price : { $multiply : ["$prices.00026", 1 ] },
}
}},
{ $match : { "priceReal.price" : {$gt : 30 } } },
{ $limit : 1 }
])
Help me anybody
Example document which I can get from db.message1064sd_00011_3744.findOne()
{
"_id" : "25906_00011_001",
"Message_ID" : 25906,
"Subdivision_ID" : 3747,
"Sub_Class_ID" : 6300,
"Checked" : 1,
"Nomencl_ID" : "10000014597",
"manufacturer_ID" : "П1170",
"disableIfZero" : 0,
"Discontinued" : 0,
"New" : 0,
"Nomencl_Group_ID" : 28,
"Nalichie" : "Мало",
"sort" : 99,
"Warehouse_ID" : "00011",
"ParentWarehouse_ID" : "00011",
"Kachestvo" : "001",
"Svobod_Nalichie" : "10",
"Svobod_sort" : 10,
"character" : [],
"prices" : {
"00014" : 1.51,
"00015" : 1.45,
"00016" : 1.41,
"00017" : 1.38,
"00018" : 1.35,
"00019" : 1.33,
"00021" : 1.31,
"00022" : 1.29,
"00023" : 1.28,
"00024" : 1.27,
"00025" : 1.25,
"00026" : 1.24
},
"price" : {
"Curr_ID" : 840,
"ChangePriceTime" : "2017-01-22 19:18:21",
"PriceUpDown" : "up",
"callPrice" : 0,
"Price_Value_RODP" : 1.24,
"Price_Value_RUR" : 72.04000000000001
},
"sName" : "чип epson m2300{m2400{mx20 8k (elp, китай)",
"sNomencl_ID" : "10000014597",
"sNomencl_Articul_Proizvod" : "elp-ch-e2300-8k",
"sItemID" : "elp-ch-e2300-8k",
"EnglishName" : "cZ277",
"begin_vl" : 121,
"Hidden_URL" : "/netshop/cZ079/cZ270/cZ277/",
"Checked_Subdivision" : 1
}
In case you want to ensure that only data from a certain data type enters your result set, for example in an aggregate query, you can add the following filter to the match:
{$match: {
// ... your query
, "priceReal.price": { $type : "double" }
}

Better way to structure this JSON data?

So I am making a 2D game using Firebase along with JavaScript and here is part of the saved file. They use JSON to store data.
{
"player" : {
"github:123123" : {
"email" : "tester#gmail.com",
"inventory" : {
"slot_1" : {
"item_id" : 0,
"item_qty" : 0
},
"slot_10" : {
"item_id" : 0,
"item_qty" : 0
},
"slot_11" : {
"item_id" : 0,
"item_qty" : 0
},
"slot_12" : {
"item_id" : 0,
"item_qty" : 0
},
"slot_13" : {
"item_id" : 0,
"item_qty" : 0
},
"slot_14" : {
"item_id" : 0,
"item_qty" : 0
},
"slot_15" : {
"item_id" : 0,
"item_qty" : 0
},
"slot_16" : {
"item_id" : 0,
"item_qty" : 0
},
"slot_17" : {
"item_id" : 0,
"item_qty" : 0
},
"slot_18" : {
"item_id" : 0,
"item_qty" : 0
},
"slot_19" : {
"item_id" : 0,
"item_qty" : 0
},
"slot_2" : {
"item_id" : 0,
"item_qty" : 0
},
"slot_20" : {
"item_id" : 0,
"item_qty" : 0
},
"slot_3" : {
"item_id" : 0,
"item_qty" : 0
},
"slot_4" : {
"item_id" : 0,
"item_qty" : 0
},
"slot_5" : {
"item_id" : 0,
"item_qty" : 0
},
"slot_6" : {
"item_id" : 0,
"item_qty" : 0
},
"slot_7" : {
"item_id" : 0,
"item_qty" : 0
},
"slot_8" : {
"item_id" : 0,
"item_qty" : 0
},
"slot_9" : {
"item_id" : 0,
"item_qty" : 0
}
},
"lowercase" : "test",
"map" : 1,
"member_level" : 2,
"signed_up" : 1437261263536,
"uid" : "github:616320",
"username" : "Test",
"version" : "1.0.0",
"x" : 50,
"y" : 20
}
}
}
As you can see, the problem lies how the inventory is structured. Is there a better way to structure so it's nicer and neat? I have read up on the Structuring Data docs on Firebase but I would appreciate your input.
This could also follow suit for not just inventory but banks and wherever large quanities of slots for items are needed in the game.
Thanks.
Well. Your version should work, however I would suggest the following structure:
{
"email" : "tester#gmail.com",
"inventory" : [{
"id": 0,
"amount": 0
},{
"id": 0,
"amount": 0
},{
"id": 0,
"amount": 0
},{
"id": 0,
"amount": 0
}],
"lowercase" : "test",
"map" : 1,
"memberLevel" : 2,
"signedUp" : 1437261263536,
"uid" : "github:616320",
"username" : "Test",
"version" : "1.0.0",
"x" : 50,
"y" : 20
}
Reasoning:
In JS camelCase is default for most projects, therefore I would use it here too.
You don't need the player attribute and github:* attribute if they are the only one. Safe the JSON to a database for players instead and keep one JSON per player.
The data structure of your inventory seems to be better fitting as an array, because you basically use every slot (if not, it's empty) and want to access it by the slot id.
If the subobject you describe is in the inventory array there is no need to call every property item, because that's obvious.

Categories