What is the mongoose schema of this json example? - mongodb

I am working on a Node.js project with MongoDb Database .
I need the schema of this json example :
I am working on a Node.js project with MongoDb Database .
I need the schema of this json example
MongoDb document :
{
"container_number": "ddd",
"container_Date": "2/2/2018",
"scannedProductArray": {
"CCR": [
{
"ScannedDate": {
"$date": "2018-03-28T20:54:57.663Z"
},
"productNumber": "4656874974",
"productType": "CCR"
},
{
"ScannedDate": {
"$date": "2018-03-28T20:55:23.698Z"
},
"productNumber": "4656874974",
"productType": "CCR"
}
],
"CCH": [
{
"ScannedDate": {
"$date": "2018-03-28T21:25:16.202Z"
},
"productNumber": "4656874974",
"productType": "CCR"
},
{
"ScannedDate": {
"$date": "2018-03-28T21:26:08.696Z"
},
"productNumber": "4656874974",
"productType": "CCR"
}
]
}
}

container_number: String,
container_Date: String,
scannedProductArray:{CCR:[ScannedDate: {
date:type:Date,default:Date.now
},
"productNumber:Number,
"productType": "String"],CCH[:[ScannedDate: {
date:type:Date,default:Date.now
},
"productNumber:Number,
"productType": "String"]}
May be this one helps you.

I'd like to define schemas like this:
const Product = {
ScannedDate: {
type: Object,
},
productNumber: {
type: String,
},
productType: {
type: String,
default: 'CCR',
}
};
const Item = {
itemName: {
type: [Product],
},
};
const Container = {
container_number: {
type: String,
},
container_Date: {
type: String
},
scannedProductArray: {
type: Object, // Item
}
};
If the CCR/CCH fields are dynamic, I can just use type: Object rather than a certain structure. And I validate these array items by myself instead of mongoose.

Related

MongoDB update a specific nested field

Hi I am trying to update nested filed , but couldn't able to do so.
Here is the sample data,
[{
"_id": {
"$oid": "632ec4128f567511dcd80ed9"
},
"company_id": 1,
"contact_id": 1001,
"roles_to_be_accepted": {
"ROLE#04": {
"assigned_data": {
"assigned_3HFui": {
"is_idle": false,
"send_for_acceptance_date": 1664009233,
"action_date": ""
},
"assigned_b1J9t": {
"is_idle": false,
"send_for_acceptance_date": 1664009233,
"action_date": ""
}
}
},
"ROLE#02": {
"assigned_data": {
"assigned_uPJI1": {
"is_idle": false,
"send_for_acceptance_date": 1664009233,
"action_date": ""
}
}
}
}
}]
Now I want to update that is_idle field to true. I have tried in this way
let query = { contact_id: 1, company_id: 1001};
const db = this.client.db("dbname");
const col= db.collection("collection_name");
col.update(query, {
'$set': { "roles_to_be_accepted.assigned_data.is_idle": true }
});

Mongoose update only fields available in request body

I am trying to update one document using findOneAndUpdate and $set but I clearly missing something very crucial here because the new request is overwriting old values.
My Device schema looks like this:
{
deviceId: {
type: String,
immutable: true,
required: true,
},
version: {
type: String,
required: true,
},
deviceStatus: {
sensors: [
{
sensorId: {
type: String,
enum: ['value1', 'value2', 'value3'],
},
status: { type: Number, min: -1, max: 2 },
},
],
},
}
And I am trying to update the document using this piece of code:
const deviceId = req.params.deviceId;
Device.findOneAndUpdate(
{ deviceId },
{ $set: req.body },
{},
(err, docs) => {
if (err) {
res.send(err);
} else {
res.send({ success: true });
}
}
);
And when I try to send a request from the postman with the body that contains one or multiple sensors, only the last request is saved in the database.
{
"deviceStatus": {
"sensors": [
{
"sensorId": "test",
"status": 1
}
]
}
}
I would like to be able to update values that are already in the database based on req.body or add new ones if needed. Any help will be appreciated.
The documentation said:
The $set operator replaces the value of a field with the specified
value.
You need the $push operator, it appends a specified value to an array.
Having this documents:
[
{
_id: 1,
"array": [
2,
4,
6
]
},
{
_id: 2,
"array": [
1,
3,
5
]
}
]
Using $set operator:
db.collection.update({
_id: 1
},
{
$set: {
array: 10
}
})
Result:
{
"_id": 1,
"array": 10
}
Using $push operator:
db.collection.update({
_id: 1
},
{
$push: {
array: 10
}
})
Result:
{
"_id": 1,
"array": [
2,
4,
6,
10
]
}
you want to using $push and $set in one findOneAndUpdate, that's impossible, I prefer use findById() and process and save() ,so just try
let result = await Device.findById(deviceId )
//implementation business logic on result
await result.save()
If you want to push new sensors every time you make request then update your code as shown below:
const deviceId = req.params.deviceId;
Device.findOneAndUpdate(
{ deviceId },
{
$push: {
"deviceStatus.sensors": { $each: req.body.sensors }
}
},
{},
(err, docs) => {
if (err) {
res.send(err);
} else {
res.send({ success: true });
}
}
);
Update to the old answer:
If you want to update sensors every time you make request then update your code as shown below:
const deviceId = req.params.deviceId;
Device.findOneAndUpdate(
{ "deviceId": deviceId },
{ "deviceStatus": req.body.sensors },
{ upsert: true },
(err, docs) => {
if (err) {
res.send(err);
} else {
res.send({ success: true });
}
}
);

How to update any amount of fields in a nested documen in Mongoose?

I need to update different fields of a nested array in Mongoose. Sometimes I will send runId and runStatus, some other times siteFetched and some other times siteInfo.
I have tried with the following code but the $set operator replaces the old fields.
The model:
campaignId: { type: String },
keywords: [{
keyword: { type: String },
serp: {
runId: { type: String },
runStatus: { type: String },
siteFetched: { type: Boolean },
sitesInfo: [{
title: { type: String },
url: { type: String },
description: { type: String },
}],
},
},
],
Here is the code to update
const campaign = await Campaign.findOneAndUpdate(
{ _id: campaignId, "keywords.keyword": keyword },
{
$set: { "keywords.$.apifySerp": {...serp }},
}
);
the value for serp varies like
const serp = {
runId: '1kLgbnvpADsDJyP1x',
runStatus: 'READY'
}
and
const serp = {
siteFetched: true
}
Here is the code that solved my problem.
const serp = {
siteFetched: true,
};
let update = Object.keys(serp).reduce((acc, cur) => {
acc[`keywords.$.apifySerp.${cur}`] = serp[cur];
return acc;
}, {});

Problem using aggregation in mongodb retrieving data from two collections

i am strugling with a query that i don't know how to perform... I have two collections,
Tarifas Collection
tarifaConfig = new Schema({
producto: { type: String },
titulo: { type: String },
bloqueo: { type: Boolean },
margen: { type: Number },
precioVenta: { type: Number },
precioVentaIva: { type: Number },
})
const tarifaSchema = new Schema({
codigo: { type: String },
titulo: { type: String },
margen: { type: Number },
estado: { type: Boolean },
bloqueo: { type: Boolean },
configs: [tarifaConfig]
})
Producto Collection
const productosSchema = new Schema({
ref: { type: String },
nombre: { type: String },
precioCompra: { type: Number },
precioCompraIva: { type: Number },
precioVenta: { type: Number },
precioVentaIva: { type: Number },
iva: { type: Number },
})
Now i am using an Aggregation method to retrieve both collection in a response
productosModel.aggregate([
{
$match: { _id: ObjectId(req.params.id) }
},
{
$lookup: {
from: "tarifas",
as: "tarifas",
pipeline: []
}
}
]).then((producto) => {
res.json(producto);
})
This is working and gives me both collections in the response... but..
In tarifa's collection i have a propertie called 'configs' that is an array with lot of sub collections... this sub collections are a config of each product that i have,
So what i need to do is, retrieve all tarifas that has a configs for the product, and if the configs does not contain retrieve the tarifa with a empty array.
Expected result
{
ref: 'rbe34',
nombre: 'bike',
precioCompra: 10,
precioCompraIva: 12.1,
precioVenta: "",
precioVentaIva: "",
iva: 21,
tarifas:[
{
codigo: 'NOR',
titulo: 'Normal tarifa',
margen: 33,
estado: true,
bloqueo: true,
configs: [], ///HERE I NEED A EMPTY ARRAY IF THERE IS NOT ANY CONFIG THAT MATCH WITH THE PRODUCT ID,
}
]
}
i tried to add $match in my aggregation pipeline.
productosModel.aggregate([
{
$match: { _id: ObjectId(req.params.id) }
},
{
$lookup: {
from: "tarifas",
as: "tarifas",
pipeline: [
{ $match: { 'configs.producto': req.params.id } }
]
}
}
])
But if there is not any config that match the product it doesn't retrieve the rest of Tarifa's collection
It seems you are trying to $filter the array after you retrieve it.
This pipeline will return only the configs for which the producto field from the config matches the ref field from the product.
[
{
$match: { _id: ObjectId(req.params.id) }
},
{
$lookup: {
from: "tarifas",
as: "tarifas",
pipeline: [
{
$addFields: {
"tarifas.configs":{ $filter:{
input: "$tarifas.configs",
cond: {$eq:["$$this.producto","$ref"]}
} }
}
}
]
}
},
]
Change the fields in the $eq array to the ones you need to match.

Meteor Mongo add subdocument

I have a collection documents MasterPropinsis like this :
{
"_id": "4HSb7bbjFBzRSftXu",
"nama": "Yogyakarta",
"kabupaten": [
{
"id": "KulonProgo",
"nama": "Kulon Progo",
"kecamatan": [{ "nama": "Kalibawang" },{ "nama": "Nanggulan" }]
},
{
"id": "Sleman",
"nama": "Sleman",
"kecamatan": [{ "nama": "Depok" },{ "nama": "Berbah" }]
},
{
"id": "Bantul",
"nama": "Bantul",
"kecamatan": []
}
]
}
At kabupaten:Bantul, I want to Add subdocument kecamantan:XXX, with this code :
Masterpropinsis.update(
{
_id: Session.get('idKabupaten').toString(),
'kabupaten.id': Session.get('idKecamatan').replace(" ", "")
},
{
$addToSet: {
'kabupaten.kecamatan': {
nama: nama,
createdAt: new Date(),
createBy: CreateBy,
createByID: CreateByid
}
}
},
{
validate: true
});
But I get this error:
Uncaught Error: Not permitted. Untrusted code may only update documents by ID. [403]
Here is an example try this
var docId = Session.get('idKabupaten'); // usally toString is not nesserry unless you do something unusual
Masterpropinsis.update({_id: docId }, {
$push: {
'kabupaten.kecamatan': {
nama: nama,
createdAt: new Date(),
createBy: CreateBy,
createByID: CreateByid
}
}
}); // validate true also is the default unless again you do something unusual
you can see we only supply {_id: docId} in the selector the error says in client you can only update by the ID in the server you can do any selector. Also hopefully you can have Allow/Deny rules to allow updates from the client? http://docs.meteor.com/#/full/allow