I have the following collections
const TransactionSchema = mongoose.Schema({
schedule: {
type: mongoose.Schema.ObjectId,
required: true,
ref: "Schedule"
},
uniqueCode: {
type: String,
required: true
},
item: {
type: mongoose.Schema.ObjectId,
required: false,
ref: "Item"
},
created: {
type: Date,
default: Date.now
},
status: {
type: String,
required: false
},
})
schedule
const ScheduleSchema = mongoose.Schema({
start: {
type: Date,
required: true,
},
end: {
type: Date,
required: false,
},
questions: {
type: Array,
default: [],
},
items: [{
item: {
type: mongoose.Schema.ObjectId,
require: true,
ref: "Item"
},
stock: {
type: Number,
required: true
}
}],
status: {
type: String,
required: false
},
})
I want to return how many times the item appear in transaction and reduce it with the number of total item I have in array of objects items in schedule collection.
For example I have the following data:
transaction
[
{
"_id":ObjectId('626134d547c28b6ecc6d0c6c'),
"schedule":624edc44ac2edc1cf07821de,
"uniqueCode":"312312312312",
"created":2022-04-21T10:41:25.901+00:00,
"item": 61efd8a812432135c08a748d,
"status": "Active"
},
{
"_id":ObjectId('62615ea3db7d00061b7cc437'),
"schedule":624edc44ac2edc1cf07821de,
"uniqueCode":"1213123123",
"created":2022-04-21T13:39:47.351+00:00,
"item": 624c6b26a41c439987b1eb42,
"status": "Active"
}
]
schedule
[
{
"_id":ObjectId('624edc44ac2edc1cf07821de'),
"start":2000-01-01T00:00:00.000+00:00,
"end":2000-01-01T00:00:00.000+00:00,
"questions":[
12,
32,
122
],
"items":[
{
"item":61efd8a812432135c08a748d,
"stock":120
},
{
"item":624c6b26a41c439987b1eb42,
"stock":1000
}
],
"status":"Active"
},
]
Item
[
{
"_id": ObjectId('61efd8a812432135c08a748d'),
"name": "Samsung S21"
},
{
"_id": ObjectId('624c6b26a41c439987b1eb42'),
"name": "Iphone 10"
}
]
I want to get the following result:
[
{
"item":"Samsung S21",
"total":119
},
{
"item":"Iphone 10",
"total":999
}
]
Note: I want the query to query one schedule data only so the result only shows the items in that schedule. The first row shows 119 from total stock of item 120 - 1 which is how many times the item appeared in transaction (where the status is active). The second row shows 999 because the item has appeared in one transaction.
Thank you. Sorry for my bad English.
Related
This is my first post so please bear with me. I am building a LinkedIn clone and I am trying to keep track of the work experience, projects and courses of the users, and those will be kept in an array of objects inside of the User schema. Now let's say a user will try to add or update one of the elements in one of those arrays, I have the user ID and I am passing it to findOneAndUpdate() as the filter.
Here is my User schema:
const userSchema = new mongoose.Schema({
user_id: {
type: String,
required: [true, 'User ID required.'],
unique: true,
immutable: true,
},
name: {
type: String,
required: [true, 'Name required.'],
},
email: {
type: String,
required: [true, 'Email required.'],
unique: true,
lowercase: true,
immutable: true,
},
title: {
type: String,
},
location: {
type: String,
},
phone_number: {
type: String,
},
contact_email: {
type: String,
},
photo: {
type: String,
},
website: {
type: String,
},
backdrop: {
type: String,
},
summary: {
type: String,
},
work: {
type: String,
},
connections: {
type: Number,
},
projects: [
{
title: {
type: String,
},
description: {
type: String,
},
start_date: {
type: Date,
},
end_date: {
type: Date,
},
technologies: {
type: String,
},
picture: {
type: String,
},
},
],
skills: [{
skill: {
name: {
type: String,
},
level: {
type: String,
},
},
}],
experience: [
{
company: {
type: String,
},
logo: {
type: String,
},
title: {
type: String,
},
location: {
type: String,
},
start_date: {
type: Date,
},
end_date: {
type: Date,
},
description: {
type: String,
},
},
],
education: [
{
school: {
type: String,
},
logo: {
type: String,
},
degree: {
type: String,
},
location: {
type: String,
},
start_date: {
type: Date,
},
end_date: {
type: Date,
},
description: {
type: String,
},
},
],
languages: [
{
name: {
type: String,
},
level: {
type: String,
},
},
],
awards: [
{
title: {
type: String,
},
date: {
type: Date,
},
awarder: {
type: String,
},
summary: {
type: String,
},
},
],
courses: [
{
title: {
type: String,
},
number: {
type: String,
},
school: {
type: String,
},
start_date: {
type: Date,
},
end_date: {
type: Date,
},
description: {
type: String,
},
},
],
});
And in my UserController.ts file, I tried using this:
const updateUser = async (req: Request, res: Response) => {
try {
const filter = { user_id: req.body.user_id };
const update = req.body;
const updatedUser = await User.findOneAndUpdate(filter, update, {
new: true,
upsert: true,
});
res.status(201).json({
status: 'success',
data: {
user: updatedUser,
},
});
} catch (err) {
res.status(400).json({
status: `ERROR: ${err}`,
message: 'error updating user',
});
}
};
And in my request using the format of the schema but that didn't work out as expected. I know mongoose will automatically give it an _id field to each of the individual objects in the array, but again, I have had no luck updating them. I tried sending a PATCH request with this as the body to add a skill like so:
{
"user_id": "xxxxxxxxxxxxxxxx",
"title": "Mr.",
"skills" : {
"name": "Flute",
"level": "Novice"
}
}
And this was the response I got. It created a skill but didnt add the data in the skill object:
{
"status": "success",
"data": {
"user": {
"_id": "63d3715f2ef9698667230a53",
"user_id": "xxxxxxxxxxxxxxxx",
"name": "Jonathan Abitbol",
"email": "yoniabitbol1#gmail.com",
"projects": [],
"skills": [
{
"_id": "63d4068d2df30c9e943e4608"
}
],
"experience": [],
"education": [],
"languages": [],
"awards": [],
"courses": [],
"__v": 0,
"title": "Mr."
}
}
}
Any help on how to add/edit the nested objects would be appreciated.
Let's take the default oneOf example from rjsf docs:
const schema = const schema = {
type: 'object',
oneOf: [
{
properties: {
lorem: {
type: 'string'
}
},
required: ['lorem']
},
{
properties: {
ipsum: { type: 'string' }
},
required: ['ipsum']
}
]
}
official codepen demo here
Is it possible to add a label to the select that switches between oneOf items?
You can add a field (in the example I named it "dropdownField") whose value is the condition for showing the other fields.
That field can have a title just like the others.
{
type: "object",
properties: {
dropdownField: {
title: "Your label goes here",
type: "string",
enum: ["Option 1", "Option 2"],
default: "Option 1",
},
},
dependencies: {
dropdown: {
oneOf: [
{
properties: {
dropdown: { enum: ["Option 1"] },
lorem: {
type: "string",
},
},
required: ["lorem"],
},
{
properties: {
dropdown: { enum: ["Option 2"] },
ipsum: {
type: "string",
},
},
required: ["ipsum"],
},
],
},
},
}
You can read more at the "dependencies" page.
I have an query object
const query = {
brand : BMW,
yearFrom : 2000,
yearTo : 2003,
price : 7000,
};
I am trying to find every BMW which is made between 2000 and 2003 included.
I am trying in this way but it doesn't work
if (query.yearFrom) {
return offerModel.find({query,year : {$gte : query.yearFrom }}, function(err,arr) {console.log(err,arr)}).skip(offset).limit(12);
}
Here's the mongoose schema
const mongoose = require('mongoose');
const offerSchema = new mongoose.Schema({
brand: {
type: String,
required: true,
},
model: {
type: String,
required: true,
},
year: {
type: Number,
required: true,
},
color: {
type: String,
required: true,
},
power: {
type: Number,
required: true,
},
mileage: {
type: Number,
required: true,
},
populatedState: {
type: String,
required: true,
},
price: {
type: Number,
required: true,
},
condition : {
type: String,
required: true,
},
doors: {
type: Number,
required: true,
},
description: {
type: String,
required: true,
},
transmission: {
type: String,
required: true,
},
engineType: {
type: String,
required: true,
},
category: {
type: String,
required: true,
},
imageURLs : [],
imageIds : [],
creator: {
type: mongoose.Types.ObjectId,
ref: 'user'
},
})
module.exports = mongoose.model('offers', offerSchema);
Sample data from database
_id:60fe98301b76642e04a31c45,
imageURLs:[],
imageIds : [],
brand:BMW,
model:335,
year:2000,
color:White,
doors:4,
power:130
mileage:30000,
populatedState:Sofia,
price:7000,
condition:Used,
description:qweqweqweqe,
transmission:Automatic gearbox,
engineType:Petrol,
category:Sedan,
creator:60fe97d11b76642e04a31c44,
__v:0,
If i put only query it find brand,model and etc.But it doesn't get year search correctly.
I will be glad if you guys have some ideas how can i fix that
Thanks !
Try this
offerModel.find({
$and: [
{ brand :query.brand },
year : {
$gte: query.yearTo,
$lt: query.yearFrom
}
]
}, function (err, results) {
...
}
I`ve modeled a document to be:
let UserSchema = new Schema({
name: { type: String, required: true, max: 50, unique: true },
email: {type: String, required: true, max: 50, unique: true},
password: {type: String, required: true, max: 20},
monitoringProject: [
{
projectName: { type: String, required: true, max: 30},
token: { type: String, required: true},
dispositives: [
{
name: { type: String, required: true, max: 15},
value: { type: String, required: true},
token: { type: String}
}
]
}
],
controlProject: [
{
projectName: { type: String, required: true, max: 30},
token: { type: String, required: true},
dispositives: [
{
name: { type: String, required: true, max: 15},
value: { type: String, required: true},
token: { type: String}
}
]
}
]
});
In the monitoringProject, for example, I can log too many different projects, and, to each project, I can log too many dispositives. So, I have nested arrays. In other project, where I have just one project, and many dispositives, I can list them and search for just one dispositive. But in this case, like this:
[ { "_id": "5ee18ece1ea5af75bae55f91", "monitoringProject": [ { "dispositives": [ { "_id": "5ee18ef31ea5af75bae55f9c", "name": "Dispositivo 1", "token": "$2b$15$NntmY9ihNZ7R1Vg1WMtmzOSjlfCoKIuHLofF6g5tKXA57WLLc2At2" }, { "_id": "5ee18ef81ea5af75bae55f9e", "name": "Dispositivo 2", "token": "$2b$15$OZB7HbDLvonsv6A71ozW7.yVY2vJOipTCj0AH7XzoafQwwDho.jpm" }, { "_id": "5ee18efc1ea5af75bae55fa0", "name": "Dispositivo 3", "token": "$2b$15$0hpDzNeTO2qJzBVyAHc/UesrnIRi/YpeAlpCLewNhmfl6fe3SEN0i" }, { "_id": "5ee2278d0754817853134bf3", "name": "Dispositivo 4", "token": "$2b$15$ldC5/CyxITPJGUvtXJ.2S.D6a3FBftg6ctQeS4ne/9xpMP5PPiszK" }, { "_id": "5ee2288956fc4c7870044395", "name": "Dispositivo 6", "token": "$2b$15$3rJt.gXEi/gALvrwxVUsWuwF2RUcBmZcoFOQeXwF45ZuKQrB3AGHG" }, { "_id": "5ee6d23d1756b7a8384bcff0", "name": "Dispositivo 7", "token": "$2b$15$C3I9STKJpf9i/7hzhvHEs.IizXpOEmgRTD3hd7ZSdcvATb73Z0zNC" } ], "_id": "5ee18ede1ea5af75bae55f94", "projectName": "Projeto 2", "token": "$2b$15$xaytMbMnGd3BMAGapX8nn.imvkQKetqx0OIlUUyP3gCxlKz/G6DiG" } ] } ]
I can only list all the Dispositives. I want to return just, for example, "Dispositivo 2".
I used to querys:
await User.find({ email: req.body.email, monitoringProject: { $elemMatch: { token: req.body.projecttoken, dispositives: { $elemMatch: { token: req.body.dispositivetoken } } } } }, { "monitoringProject.$.dispositives": 1} )
or
await User.find({ email: req.body.email, 'monitoringProject.token': req.body.projecttoken, 'monitoringProject.dispositives.token': req.body.dispositivetoken}, { 'monitoringProject.dispositives.$': 1 })
Using find or findOne. How can I return just the document I want? I tried so many different ways, but with no lucky.
I have a document like the following one:
{
_id: "00112233",
array: [
{
_id: "potatoes",
amount: 5
},
{
_id: "carrots",
amount: 6
}
]
}
and I need to update or push the documents so that if there is one in the array, it gets replaced, if not, it gets pushed.
If i try to do an update like this:
db.collection.update(
{ _id: "00112233" },
{
"$push": { "array": { "$each": [
{
_id: "potatoes",
amount: 6
},
{
_id: "apples",
amount: 2
}
]}}
}
)
In the database I will find two "potatoes" field. But if I try to replace the "push" with a "addToSet" I won't have the "potatoes" field updated.
Is there any way I can do this in only one query?
Unfortunately, you can't achieve the result that you are expecting in single update operation.
The addToSet doesn't work for this scenario because the array has embedded documents. addToSet checks for both the attribute names and values whether it matches. If match is found, it does nothing. If the match is not found, it adds the data to the array attribute.
In the above case for "potatoes", the amount value of potatoes doesn't match. So it inserts a new element into array. So the result has two potatoes with 2 different values.
{
_id: "potatoes",
amount: 6
}
You may need to perform two update operations.
1) Update the value of an array field if it exists using $set
db.collection.update(
{ _id: "00112233", "array._id": "potatoes"},
{
"$set": { "array.$":
{
_id: "potatoes",
amount: 7
}
},
}
);
2) Add the new element to an array field if it doesn't exists using $addToSet
db.collection.update(
{ _id: "00112233"},
{
"$addToSet": { "array":
{
_id: "apples",
amount: 7
}
},
}
);
you need to use $set instead of $push/$addToSet.
https://docs.mongodb.com/manual/reference/operator/update/set/
Had a similar issue and tried notion quest's approach and it did work.My schema was as follows
const MatchInstanceSchema = new Schema({
_id: false,
pseudoKey: { type: String, required: true, unique: true },
service: { type: String, required: true },
region: { type: String, required: true },
team1: {
name: { type: String, required: true },
price: { type: String, required: true }
},
team2: {
name: { type: String, required: true },
price: { type: String, required: true }
},
drawPrice: { type: String, required: true },
url: { type: String, required: true }
})
const MatchSchema = new Schema({
pseudoKey: { type: String, required: true, unique: true },
sport: { type: String, required: true },
league: { type: String, required: true },
date: { type: Date, required: true },
team1: { type: String, required: true },
team2: { type: String, required: true },
matchInstances: [MatchInstanceSchema]
})
I wanted to update the following matchInstances subdocument if there exists a match whose pseudoKey was same as the top level(parent document) pseudoKey without
duplicating the value and create a new entry in the matchInstances subdocument if it did not exist.
{
"_id" : ObjectId("5b47d47e7fd01d29178aa3a5"),
"pseudoKey" : "newcastle-tottenham",
"sport" : "Soccer",
"league" : "Premier League",
"date" : ISODate("2018-08-11T11:30:00.000Z"),
"team1" : "Newcastle",
"team2" : "Tottenham",
"matchInstances" : [
{
"team1" : {
"name" : "Newcastle",
"price" : "74.6"
},
"team2" : {
"name" : "Tottenham",
"price" : "2.06"
},
"pseudoKey" : "newcastle-tottenham",
"service" : "Betin",
"region" : "Kenya",
"drawPrice" : "3.45",
"url" : "https://web.betin.co.ke/Sport/SubEventOdds.aspx?SubEventID=16701401"
}
]
This was my solution
//If it already exists we just want to update with the new values without
//duplicating
Match.findOneAndUpdate(
{ pseudoKey: pseudoKey, "matchInstances.service": service },
{ $set: { "matchInstances.$": matchInstances[0] } }
//If it does not exist we want to add it as a new entry into the matchInstances
//subdocument
Match.findOneAndUpdate(
{ pseudoKey: pseudoKey },
{ $addToSet: { matchInstances: matchInstances } }
)