Advanced search with mongoose - database

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) {
...
}

Related

How do I update individual fields in nested objects that are in arrays in MongoDB using Mongoose?

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.

I am having difficulty accessing this nested array to carry out an update

SCHEMA
Below is my schema structure, kindly correct me if I am getting it wrong. I want to be able to update the ConnectState from false to true using an ObjectId
phones: {
type: String,
required: true,
},
User: {
type: mongoose.Schema.Types.ObjectId,
ref: "user",
// required: true,
},
Userpost: {
type: mongoose.Schema.Types.ObjectId,
ref: "userpost",
// required: true,
},
friendshipStatus: [
{
isFriend: {
FProfile: {
type: mongoose.Schema.Types.ObjectId,
ref: "profile",
},
ConnectStatus: {
type: Boolean,
default: false,
},
},
},
],
});
What I have tried
I want to update the Boolean value on ConnectStatus from false to true. I know I am getting the process wrong.
const result = await Profile.updateOne(
{ "friendshipStatus.isFriend.FProfile": uid },
{ $set: { "friendshipStatus.$.isFriend.ConnectStatus": true } },
{ arrayFilters: [{ "friendshipStatus.isFriend.FProfile": uid }] }
);
Try with:
const result = await Profile.update(
{ 'friendshipStatus.isFriend.FProfile': uid },
{ $set: { 'friendshipStatus.$.isFriend.ConnectStatus': true } },
);

model in mongodb user and product ref not working

my code does not working model of mongodb user and product ref does not work for me
and showing
error
Order validation failed: user: Path user is required., orderItems.0.product: Path product is required.
how can i solve it please help me
import mongoose from "mongoose";
const orderSchema = mongoose.Schema(
{
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "User",
},
orderItems: [
{
name: { type: String, required: true },
qty: { type: Number, required: true },
image: { type: String, required: true },
price: { type: Number, required: true },
product: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "Product",
},
},
],
shippingAddress: {
address: { type: String, required: true },
city: { type: String, required: true },
postalCode: { type: String, required: true },
country: { type: String, required: true },
},
paymentMethod: {
type: String,
required: true,
},
paymentResult: {
id: { type: String },
status: { type: String },
update_time: { type: String },
email_address: { type: String },
},
taxPrice: {
type: Number,
required: true,
default: 0.0,
},
shippingPrice: {
type: Number,
required: true,
default: 0,
},
itemsPrice: {
type: Number,
required: true,
default: 0,
},
totalPrice: {
type: Number,
required: true,
default: 0,
},
isPaid: {
type: Boolean,
required: true,
default: false,
},
paidAt: {
type: Date,
},
isDelivered: {
type: Boolean,
required: true,
default: false,
},
deliveredAt: {
type: Date,
},
},
{
timestamps: true,
}
);
export const Order= mongoose.model("Order", orderSchema);
enter image description here

Get only the length of mongoose virtual populate

I would like to know if there is a way in Mongoose of getting the number of matching localField/foreignField as virtual field, without retrieving all the documents through virtual population.
Example:
const ForumThreadSchema = new Schema({
code: { type: Number, required: true, unique: true },
title: { type: String, min: [10, 'Too short title'], max: [200, 'Too long title'], required: true },
description: { type: String, min: [10, 'Too short description'], max: [2000, 'Too long description'], required: true },
creation_date: { type: Date, default: Date.now, required: true },
updated_date: { type: Date, default: Date.now, required: true },
_authorId: { type: Schema.ObjectId, ref: 'User', required: true },
_forumId: { type: Schema.ObjectId, ref: 'Forum', required: true }
}, {
collection: 'ForumThreads',
toObject: { virtuals: true },
toJSON: { virtuals: true }
});
const ForumMessageSchema = new Schema({
code: { type: Number, required: true, unique: true },
content: { type: String, min: [10, 'Too short message content'], max: [2000, 'Too long message content'], required: true },
creation_date: { type: Date, default: Date.now, required: true },
update_date: { type: Date, default: Date.now, required: true },
_authorId: { type: Schema.ObjectId, ref: 'User', required: true },
_forumThreadId: { type: Schema.ObjectId, ref: 'ForumThread', required: true },
_parentMessageId: { type: Schema.ObjectId, ref: 'ForumMessage' }
}, {
collection: 'ForumMessages'
});
The virtual populate on the forum thread schema retrieves me all the message documents. I need a virtual field with only their number if possible.
ForumThreadSchema
.virtual('messages', {
ref: 'ForumMessage',
localField: '_id',
foreignField: '_forumThreadId'
});
ForumThreadSchema
.virtual('messages_count')
.get(function() {
return this.messages.length;
});
The second virtual only works if the population of the first one is done.
I also want to mantain the virtual populate but I would like to find a way of getting the number of matching documents without use it (in server APIs that not need all message documents but only their size).
Is it possible?
You just need to add the count option:
ForumThreadSchema
.virtual('messages_count', {
ref: 'ForumMessage',
localField: '_id',
foreignField: '_forumThreadId',
count: true
});
And then when you can populate just the count:
ForumThread.find({}).populate('messages_count')
Doc: https://mongoosejs.com/docs/populate.html#count

Angular is not sending objects in objects

I'm sending this JSON with Angular.js to my node.js/express.js service:
{
"name": "MyGuitar",
"type": "electric",
"userid": "123",
"likes": 0,
"dislike": 0,
"guitarParts": {
"body": {
"material": "/content/img/hout.jpg",
"_id": "5566d6af274e63cf4f790858",
"color": "#921d1d"
},
"head": {
},
"neck": {
"material": "/content/img/hout.jpg",
"_id": "556d9beed90b983527c684be",
"color": "#46921d"
},
"frets": {
},
"pickup": {
},
"bridge": {
},
"buttons": {
}
}
}
The guitarParts are not saved in the MongoDB database.
Mongoose inserts the following:
Mongoose: guitars.insert({ name: 'MyGuitar', type: 'electric', userid: '123', likes: 0, _id: ObjectId("557023af9b321b541d4d416e"), guitarParts: [], __v: 0})
This is my Mongoose model:
guitarPart = new Schema({
id: { type: String, required: true },
color: { type: String, required: true },
material: { type: String, required: true },
x: { type: Number, required: false },
y: { type: Number, required: false },
width: { type: Number, required: false },
height: { type: Number, required: false},
});
guitarParts = new Schema({
body: [guitarPart],
neck: [guitarPart],
head: [guitarPart],
bridge: [guitarPart],
frets: [guitarPart],
pickup: [guitarPart],
buttons: [guitarPart]
});
guitar = new Schema({
name: { type: String, required: true, unique: false },
type: { type: String, required: true },
userid: { type: String },
likes: { type: Number },
dislikes: { type: Number },
guitarParts: [guitarParts],
kidsguitar: { type: Boolean },
lefthanded: { type: Boolean },
assemblykit: { type: Boolean }
},
{
collection: 'guitars'
});
I don't know what's going wrong. Any ideas?
According to the mongoose documentation of Subdocuments says: Sub-documents are docs with schemas of their own which are elements of a parents document array
And in your schema you provided: guitarParts is not an array, it is an object and a guitarPart is not array it is an object too. So that's why it is not saving.
So the correct way to model your Schema it would be:
var guitarDefinition = {
_id: {type: String, required: true},
color: {type: String, required: true},
material: {type: String, required: true},
x: Number,
y: Number,
width: Number,
heigth: Number
};
var guitarSchema = Schema({
name: { type: String, required: true, unique: false },
type: { type: String, required: true },
userid: String,
likes: Number,
dislikes: Number ,
kidsguitar: Boolean,
lefthanded: Boolean ,
assemblykit: Boolean,
guitarParts: {
body: guitarDefinition,
neck: guitarDefinition,
head: guitarDefinition,
bridge: guitarDefinition,
frets: guitarDefinition,
pickup: guitarDefinition,
buttons: guitarDefinition
}
});
Actually I have run in my computer and it is saving you can see my complete code here: https://gist.github.com/wilsonbalderrama/f10c38f9fb510865edc2

Resources