Mongoose update Query - mongodb

Hello All I am attempting to make an update using mongoose and I can't seem to get it working. This is the data that I am saving.
var mongoose = require('mongoose');
var DataSchema = new mongoose.Schema({
advisorEmail: {
type: String
},
data: {
type: Array
},
client: {
type: String,
required: true,
trim: true
},
accountBalance: {
type: Number,
required: true,
trim: true
},
description: {
type: String,
required: true,
trim: true
},
AccountValue: {
type: Number,
required: true,
trim: true
},
moneyMarket: {
type: Number,
required: true,
trim: true
},
buyingPower: {
type: Number,
required: true,
trim: true
},
netBalance: {
type: Number,
required: true,
trim: true
},
advisorPercentage: {
type: Number,
required: true,
trim: true
}
});
var Data = mongoose.model('Table', DataSchema);
module.exports = Data;
Below will be the code I am writing to be able to update the data array
Data.update({
"advisorEmail":"Travis#travis.com"
},
{"$push":
{ "data":{"client": "Tester", "accountBalance": 21342,
"description": "test From Nodejs", "AccountValue": 123234,
"moneyMarket": 11000, "buyingPower": 01, "netBalance": 10,
"advisorPercentage": 24}}}, function(err, updateData){
if (err) throw (err);
console.log(updateData);
});
There are no errors and this is the console.log that I get back from "updateData."
{ ok: 0, n: 0, nModified: 0 }
But when I take the same structure and go into my local mongodb and do
db.tables.update({
"advisorEmail": "Travis#travis.com"
}, {
"$push": {
"data": {
"client": "bobby",
"accountBalance": 123,
"description": "TravisPUTO",
"AccountValue": 123,
"moneyMarket": 1000,
"buyingPower": 0,
"netBalance": 0,
"advisorPercentage": 1
}
}
})
it works completely fine and says this..
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
is this a mongoose issue? I'm not really sure what's wrong.
Thank you for anything you may be able to do to help me!

Please update your schema with additional fields.
advisorEmail : {type: String},
data: { type: Array },
so mongoose identified fields you update.

Related

How to develop nested condition query in mongoDB

I am pretty new to mongoDb and want to apply nested query.
I have a business schema like this:
const businessSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
},
businessType: {
type: Schema.Types.ObjectId,
ref: "businessCategory",
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
select: false,
},
review: {
type: [reviewSchema],
},
isDeleted: {
type: Boolean,
default: false,
},
},
{ timestamps: true }
);
Business has a review where user can do the review and reviewSchema is
const reviewSchema = new mongoose.Schema(
{
user: {
type: Schema.Types.ObjectId,
ref: "users",
required: true,
},
rating: {
type: Number,
enum: [1, 2, 3, 4, 5],
},
reviewArray: {
type: [singleReviewSchema],
},
},
{ timestamps: true }
);
One user can do many reviews, and it has reviewArray.
ReviewArray schema is
const singleReviewSchema = new mongoose.Schema(
{
title: {
type: String,
},
description: {
type: String,
},
isDeleted: {
type: Boolean,
default: false,
},
},
{ timestamps: true }
);
How to fetch the business with a condition business: isDeleted:false and its reviews with singleReviewSchema: isDeleted:false
I dont know your model names, so please replace path with correct names
but it might look like:
businnesModel.find({isDeleted: false})
.populate({
path: 'reviewModelName',
model: 'review',
populate: {
path: 'reviewArray',
model: 'singleReviewModelName',
match: {
isDeleted : false
}
}
})
It should provide you array of businessModel documents - even when their singleReviews array will be empty (because all of reviews are deleted, or there was zero reviews). So you have to filter it out in JS.
To avoid filtering in JS, and to do it a bit more efficient way for mongodb, you can go with aggregate instead.

How to update a property in a nested array with mongoose

I want to push a Date object from my client into the nested array 'completed_dates' but I cannot figure out how to do so, or if I would need to change my schema in order for it to work.
{
_id: 606f1d67aa1d5734c494bf0a,
name: 'Courtney',
email: 'c#gmail.com',
password: '$2b$10$WQ22pIiwD8yDvRhdQ0olBe6JnnFqV2WOsC0cD/FkV4g7LPtUOpx1C',
__v: 35,
habits: [
{
_id: 6081d32580bfac579446eb81,
completed_dates: [],
name: 'first',
type: 'good',
days: 0,
checked: false
},
{
_id: 6081d32f80bfac579446eb82,
completed_dates: [],
name: 'seconds',
type: 'bad',
days: 0,
checked: false
},
]
}
and this is my schema
const habitSchema = new mongoose.Schema({
name: String,
category: String,
color: {
type: String,
},
date_added: {
type: String,
},
completed_dates: {
type: Array,
}
})
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true,
min: 6,
max: 255,
},
email: {
type: String,
required: true,
max: 255
},
password: {
type: String,
required: true,
max: 1024,
min: 8,
},
habits: [habitSchema]
})
Here is what I have tried...
I've tried using findOneAndUpdate, using the document id of the logged in user, and trying to manipulate the update object to drill into the nested array. I can access the habits list of the correct user... using this code, but for this new problem, I want to go one level further and push to the 'completed_dates' array of a specific habit (based on name or _id).
//this only adds a habit object to the habits array.
User.findByIdAndUpdate(req.user._id,
{ $pull: { habits: { _id: itemsToDelete } } },
{ new: true , useFindAndModify: false},
function (err, data) {
if (err) {
res.send(err)
} else {
res.send(data.habits)
}
}
)
I have tried building on this existing code by trying to filter down one more level. (this doesn't work.)
const { date, name} = req.body.update
User.findByIdAndUpdate(req.user._id,
{ $push: { 'habits.$[req.body.name].completed_dates': req.body.date} },
{safe: true, upsert: true, new : true, useFindAndModify: false},
function (err, data) {
if (err) {
res.send(err)
} else {
//data.update
res.send(data.habits)
}
}
)
If anyone can link or help me out, I would appreciate it. Thanks

Mongoose - Sub Document Array Issue

I have a "Company" Model which has a number of "Rooms".
I'm able to create the Rooms no problem, and they have a link back to the Company.
The problem is that when I get the Company, the Rooms array has no items.
I can see that the Room exists and has a link back to the Company:
{
"RoomType": 0,
"AllowedRoomRoles": [
"5f999f4f542eed1b8fce5fa9"
],
"Enabled": true,
"_id": "5fb677b453658c7070bf9433",
"RoomName": "Martins Room 2",
"RoomPin": "0001",
"Company": "5fad553db19ca100161a0d8f",
"__v": 0
}
However when I do:
var company = await CompanyModel.findById('5fad553db19ca100161a0d8f');
I get the Company back but the Rooms array has no items in it.
Here are my models:
//Room Schema:
const roomSchema = new Schema({
RoomPin: String,
RoomName: String,
RoomType: { type: RoomType, default: RoomType.MeetingRoom } ,
Company: {type: Schema.Types.ObjectId, ref: 'CompanySchema'},
AllowedRoomRoles: [{type: Schema.Types.ObjectId, ref: 'RoomRoleSchema'}],
Enabled: { type: Boolean, default: true },
}, {
collection: "room"
})
//Company Schema:
const companySchema = new Schema({
CompanyName: { type: String, required: true },
CompanyLogo: { type: String, required: true },
Enabled: { type: Boolean, default: true },
CompanyIdentifier: { type: String, required: true },
CompanyWebsite: { type: String, required: true },
Rooms: [{type: Schema.Types.ObjectId, ref: 'RoomSchema'}],
}, {
collection: "company"
})
Minor update:
Seems doing it this way around is fine?
```var rooms = await RoomModel.find({'Company': company._id.toString() });

Mongoose - Validate ObjectID related document

I need to validate as required a field "product" in Model Event. Product is ObjectID reference to Product Model.
I tried with this 2 approaches, but it is not validating
product: {
type: [{
type: Schema.Types.ObjectId,
ref: 'Product',
required: true
}]
},
product: {
type: [{
type: Schema.Types.ObjectId,
ref: 'Product',
required: function () {
return this.product.length > 0
},
}]
},
The Event is being created anyway, and when I add no products, field product is an empty array.
Any idea how can I validate it?
Models:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Product = require('../models/Product');
const moment = require('moment');
const EventSchema = new Schema({
client: {
type: [{
type: Schema.Types.ObjectId,
ref: 'Client'
}]
},
product: {
type: [{
type: Schema.Types.ObjectId,
ref: 'Product',
required: true
}]
},
date: {
type: Date,
maxlength: 64,
lowercase: true,
trim: true
},
place: {
type: String,
maxlength: 1200,
minlength: 1,
},
price: {
type: Number
},
comment: {
type: String,
maxlength: 12000,
minlength: 1,
},
status: {
type: Number,
min: 0,
max: 1,
default: 0,
validate: {
validator: Number.isInteger,
message: '{VALUE} is not an integer value'
}
},
},
{
toObject: { virtuals: true },
toJSON: { virtuals: true }
},
{
timestamps: true
},
);
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Provider = require('./Provider')
const ProductSchema = new Schema({
name: {
type: String,
maxlength: 64,
minlength: 1,
required: [true, 'Product name is required'],
},
brand: {
type: String,
maxlength: 64,
minlength: 1,
},
description: {
type: String,
maxlength: 12000,
min: 1,
},
comment: {
type: String,
maxlength: 12000,
minlength: 1
},
state: {
type: String,
maxlength: 64,
minlength: 0
},
disponible: {
type: Boolean,
default: true
},
price: {
type: Number,
default: 0,
min: 0,
max: 999999
},
provider: {
type: [{
type: Schema.Types.ObjectId,
ref: 'Provider'
}]
},
category: {
type: [{
type: Schema.Types.ObjectId,
ref: 'Category'
}]
},
event: {
type: [{
type: Schema.Types.ObjectId,
ref: 'Event'
}]
},
image: {
type: [{
type: Schema.Types.ObjectId,
ref: 'Image'
}]
},
},
{
toObject: { virtuals: true },
toJSON: { virtuals: true }
},
{
timestamps: true
});
You can use custom validators feature of mongoose.
If the validator function returns undefined or a truthy value, validation succeeds. If it returns falsy (except undefined) or throws an error, validation fails.
product: {
type: [
{
type: Schema.Types.ObjectId,
ref: "Product",
required: true
}
],
validate: {
validator: function(v) {
return v !== null && v.length > 0;
},
message: props => "product is null or empty"
}
}
Now when you don't send product field, or send it empty array it will give validation error.
const notEmpty = function(users){
if(users.length === 0){return false}
else { return true }
}
const EventSchema = new Schema({
product: {
type: [{
type: Schema.Types.ObjectId,
ref: 'Product',
required: true,
validate: [notEmpty, 'Please add at least one']
}]
}
})

How to fix MongoDB geo keys error with unknown GeoJSON type error?

I'm receiving the following error when running a query in Mongo:
"errmsg" : "Can't extract geo keys: …[removed unnecessary elements]… unknown GeoJSON type: { coordinates: [ -75.17886559999999, 39.9451937 ] }
I've updated the schema to include 2dsphere, per the below:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
mongoose.promise = Promise;
const listingSchema = new Schema({
user: { type: Schema.Types.ObjectId, ref: "User" },
title: { type: String, unique: false, required: false },
parkingtype: { type: String, unique: false, required: false },
photo: { type: String, unique: false, required: false },
price: { type: Number, unique: false, required: false },
address: { type: String, unique: false, required: false },
city: { type: String, unique: false, required: false },
state: { type: String, unique: false, required: false },
zipcode: { type: Number, unique: false, required: false },
streetName: { type: String, unique: false, required: false },
neighborhood: { type: String, unique: false, required: false },
location: {
type: {
type: String,
enum: ['Point'],
required: false
},
coordinates: {
type: [Number]
}
}
});
listingSchema.index({location: '2dsphere'}); // <-- already added index
const Listing = mongoose.model("Listing", listingSchema);
module.exports = Listing;
This is the error I get back in my terminal (see bold):
errmsg:
'error processing query: ns=parky.listingsTree: GEONEAR field=location maxdist=2000 isNearSphere=0\nSort: {}\nProj: {}\n planner returned error :: caused by :: unable to find index for $geoNear query',
code: 291,
codeName: 'NoQueryExecutionPlans',
name: 'MongoError',
[Symbol(mongoErrorContextSymbol)]: {} }
Finally, for reference, this is my controllers file, and the query that is being run:
findAllNear: function(req, res) {
var long = req.query.data[0]
var lat = req.query.data[1]
var floatLong = parseFloat(long); // longitude comes through as string from url params, so it's converted to a float
var floatLat = parseFloat(lat); // same with latitude
db.Listing.syncIndexes().then((index) => {
console.log("indexes:" , index);
}); // added this snippet to see that the location index was 2d
db.Listing.find(
{location:
{$near:
{$maxDistance: 2000,
$geometry: {
type: "Point",
coordinates: [floatLong, floatLat]
}
}
}
})
.find((error, results) => { if (error) console.log(error);
console.log(JSON.stringify(results, 0, 2))})
.then(data => res.json(data))
.catch(err => res.status(422).json(err))
}