How can I increment & add to array on mongoose - javascript

In my database, I have a user table with 2 columns: score & history :
I have another table called card containing some specific information & a card _id.
Each time a specific card is clicked, I would like the '/CardClicked' router to be called for :
Additional (increment) a specific number value (1.5) on score column
Add the cart _id value on the array of history column: (to save, which card the user clicked)
I wanted to have something like that in my database:
users:
{ "_id" : 1, "score" : 6.0, "history" : [ 62k6hf45b0af050fe, 69k5hf45b0af450fg, 65k5hf45b0af450fg, ]}
{ "_id" : 2, "score" : 4.5, "history" : [ 65k5hf45b0af450fg,] }
{ "_id" : 3, "score" : 10.0, "history" : [ 66k5hf45t0af930rp, 67k5hf45b0af450fg, 62k6hf45b0af050fe, 61y5hf884b0af450vb, ] }
But, idk why it doesn't update properly on columns, however i don't have any error, that my code i made it :
My UserSchema.js :
const mongoose = require('mongoose')
const UserSchema = new mongoose.Schema({
...
score: {
type: Number,
},
history: {
type: [String]
},
createdAt: {
type: Date,
default: Date.now,
},
})
module.exports = mongoose.model('User', UserSchema)
My router.js :
app.post('/CardClicked', async function (req, res){
console.log("User ID "+req.user._id, "Card ID : "+req.body._id);
try{
const condition = { _id: req.user._id };
//the req.body._id contain the card id from my front to send that to router
const putPostID = { $addToSet: { history: req.body._id }};
const additionalPoints = {$inc : { score : 1.5 }};
await User.findOneAndUpdate(condition, additionalPoints, putPostID, {upsert: true})
}catch(err){
res.status(500).send({error: err })
}
});

Every update operation must go into one object. In your case:
User.findOneAndUpdate(condition, {
$inc: { score: 1.5 },
$addToSet: { history: req.body._id },
},
{ upsert: true },
)

Related

Mongoose Schema show the array if a friendId exist in Users Model schema

I have created a user which has its login data and into it is has some arrays including friends, groups, pages and other stuff.
But I am stucked when I want see who has sent me a friend request.
So I have am trying to create the friend request/response as in Facebook.
My logic it is for the moment when I send you a friend request I add to my array of friends and then with post request I can see at which users is my ID added and it has the status Pending.
For the moment I have tried something but I am getting empty array as response.
My code is below.
User model
const mongoose = require('mongoose');
const uniqueValidator = require('mongoose-unique-validator');
const userDataScheme = new mongoose.Schema({
firstName: String,
lastName: String,
email: {
type: String,
unique: true
},
password: String,
phone: {
number: String,
countryCode: String,
dialCode: String,
e164Number: String,
internationalNumber: String,
nationalNumber: String
},
gender: Number,
birthday_day: String,
birthday_month: String,
birthday_year: String,
friends: [{
_id: false,
friendId: String,
createdDate: { type: Date, default: Date.now },
status: Number,
}
]
},
{ autoIndex: false });
userDataScheme.plugin(uniqueValidator, { message: 'Email already in use.' });
module.exports = mongoose.model('User', userDataScheme);
user.service.js backend
const User = require("../models/user");
async function findYourPendingContact({friendId}) {
return await User.find({friends: friendId});
}
module.exports = {
findYourPendingContact
}
routes.js
routes.post("/user-friends", UserController.findYourContacts);
This is the Controller.
const userService = require("../service/user.service");
async findYourContacts(req, res, next) {
let friendId = req.body.friendId;
userService.findYourPendingContact({friendId: friendId})
.then(friends => res.json(friends))
.catch(err => next(err));
}
So seems my Database Json.
The user that added me as friend.
{
"_id" : ObjectId("620bfd2d860fd314fc538df3"),
"firstName" : "Max",
"email" : "maxmuster#outlook.de",
"lastName" : "Muster",
"password" : "$2b$10$D8l15CTZHbp/rcApqXpwT.KUbHAg0hBYp0h1qounnKFW.plDO9wKe",
"phone" : {
"number" : "1234566",
"countryCode" : "DE",
"dialCode" : "+49",
"e164Number" : "+491234566",
"internationalNumber" : "+49 1234566",
"nationalNumber" : "1234566"
},
"gender" : 1,
"birthday_day" : "13",
"birthday_month" : "8",
"birthday_year" : "1998",
"friends" : [
{
"friendId" : "6204605617d5fcc3c179f3cc", // this here is my ID
"status" : 0,
"createdDate" : {
"$date" : 1644971031461
}
}
],
"__v" : 0
}
Here are my Data on backend
{
"_id" : ObjectId("6204605617d5fcc3c179f3cc"),
"firstName" : "Test",
"email" : "test.test#outlook.com",
"lastName" : "Test",
"password" : "$2b$10$koGb0fIcdWvq2ugGQXF7.OOmoof1QCH8IKQtoMGl9MHSJuu5Xumd6",
"phone" : {
"number" : "01234567",
"countryCode" : "DE",
"dialCode" : "+49",
"e164Number" : "+4901234567",
"internationalNumber" : "+49 01234567",
"nationalNumber" : "01234567"
},
"gender" : 0,
"birthday_day" : "8",
"birthday_month" : "5",
"birthday_year" : "1994",
"__v" : 0
}
Now this is the part of my frontend when I login.
public getUserFriends(userId): Observable<any> {
const api = `${this.baseUrl}/user-friends`
return this.http.post(api, JSON.stringify({friendId: userId}), this.httpOptions).pipe(
map((response: User) => {
console.log(response);
return response;
},
(err) => {
throw err;
})
)
}
user.helper.ts
showPendingFriends(authId): Observable<any> {
return new Observable<any>(observer => {
this.userService.getUserFriends({friendId: authId}).subscribe(response => {
observer.next(response);
})
})
}
components.ts
this.userHelper.showPendingFriends(this.authService.userID).subscribe(res => console.log(res)); //this.authService.userID is my ID actually 6204605617d5fcc3c179f3cc or it can be any user ID

how to avoid duplicate key error collection in mongodb

i want to build a cart for my website, this is the schema for the cart:
const productSchema = require("./product")[1];
const cartItemSchema = new Schema<CartItem>(
{
product: productSchema,
quantity: {
type: Number,
required: true,
min: [1, "Quantity can not be less then 1."],
},
},
{
timestamps: true,
}
);
const CartSchema = new Schema(
{
userID: {
type: Schema.Types.ObjectId,
ref: "User",
},
items: [cartItemSchema],
},
{ timestamps: true }
);
module.exports = model<Cart>("Cart", CartSchema);
the problem is, when I add a product in a specific user cart, while the same product is allready added to another user cart document, I get this error:
"message":"cannot add to cart E11000 duplicate key error collection: elec-store.carts index: items.productID_1 dup key: { items.productID: null }, stack: MongoError: E11000 duplicate key error collection: elec-store.carts index: items.productID_1 dup key
this is the add function
public async add(cartItem: CartItem, userID: string): Promise<Cart> {
let cartInDB = null;
await CartModel.findOne({ userID: userID }, (err, cart) => {
cartInDB = cart;
});
if (AppUtils.hasValue(cartInDB)) {
const index = cartInDB.items.findIndex(
(item) => item.product._id.toString() === cartItem.product._id
);
if (index !== -1) {
cartInDB.items[index].quantity =
cartInDB.items[index].quantity + cartItem.quantity;
cartInDB.items[index].product._id = cartItem.product._id;
const cartAfterAdding = await cartInDB.save();
return cartAfterAdding;
} else {
await CartModel.update(
{ _id: cartInDB._id },
{ $push: { items: cartItem } }
);
}
return cartInDB;
} else {
const itemsArray: CartItem[] = [];
itemsArray.push(cartItem);
let createdCart = new CartModel({
userID: userID,
items: itemsArray,
});
await createdCart.save(); \\ this is where the problem occurs
return createdCart;
}
}
and this is how my cart looks like in mongodb document:
db.carts.find().pretty()
{
"_id" : ObjectId("60ea9fb81b2b4c048c3b1544"),
"userID" : ObjectId("60dee5e1da81bd274cd304de"),
"items" : [
{
"_id" : ObjectId("60ea9fb81b2b4c048c3b1545"),
"product" : {
"_id" : ObjectId("60e62cb21f74572b7c0b3a30"),
"name" : "tv",
"description" : "the best tv",
"categoryID" : 2,
"quantity" : "2",
"serialNumber" : "226swaq12",
"price" : 2000,
"imgUrl" : "https://www.seekpng.com/png/full/774-7744281_samsung-electronics-samsung-electronic-product-png.png"
},
"quantity" : 6,
"createdAt" : ISODate("2021-07-11T07:37:29.790Z"),
"updatedAt" : ISODate("2021-07-11T07:38:15.583Z")
},
{
"_id" : ObjectId("60eaa16b1b2b4c048c3b155d"),
"product" : {
"_id" : ObjectId("60e066009be1060748201ad3"),
"name" : "samsung tv",
"description" : "the best tv",
"quantity" : "2",
"categoryID" : 2,
"serialNumber" : "2212",
"price" : 2000,
"imgUrl" : "https://www.seekpng.com/png/full/774-7744281_samsung-electronics-samsung-electronic-product-png.png"
},
"quantity" : 9,
"updatedAt" : ISODate("2021-07-11T07:46:19.313Z"),
"createdAt" : ISODate("2021-07-11T07:44:43.764Z")
}
],
"createdAt" : ISODate("2021-07-11T07:37:29.792Z"),
"updatedAt" : ISODate("2021-07-11T07:46:19.314Z"),
"__v" : 0
}
I use mongoose.Schema to create new schemas and then when making reference to a different schema I do it like this:
product: { type: mongoose.Schema.Types.ObjectId, ref: 'product' },
If later you need to show also the product info (db.carts.find()), you can use populate() to replace the reference for all the product entries.
You can use upsert true.
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ],
hint: <document|string> // Available starting in MongoDB 4.2
}
)
For example -
db.books.update(
{ item: "ZZZ135" }, // Query parameter
{ // Replacement document
item: "ZZZ135",
stock: 5,
tags: [ "database" ]
},
{ upsert: true } // Options
)
This may help: Mongo Update

Mongoose get object in array of objects

I am using mongoose and I am trying to get users from my mongodb database, Here is what part of my json looks like
"hpCDaKverVWEYukAhAcM8NU6SP73" : {
"admin" : false,
"booksBorrowed" : [ {
"id" : "9780321831552",
"timeStamp" : 1618881802437
}, {
"id" : "9780007204496",
"timeStamp" : 1618881803678
}, {
"id" : "9780316491297",
"timeStamp" : 1618882675513
}, {
"id" : "9780440335160",
"timeStamp" : 1618882676756
}, {
"id" : "9781482287325",
"timeStamp" : 1618887153684
} ],
I am trying to get the books borrowed array
i tried creating a new schema like this
const BorrowedBook = new Schema({
id : {type: String, default: ''},
timeStamp : {type: Number, default: 0},
})
then doing this in mongoose.model
booksBorrowed: [BorrowedBook]
then I do this in server.js
const User = require('./models/user')
app.get('/api/users', function (req, res) {
User.find(function (err, users) {
console.log(users)
})
})
but it just prints this
booksBorrowed: [ [Object], [Object], [Object], [Object], [Object] ],
What am I doing wrong?
You are doing nothing wrong, its just console.log(users) printing this, since it doesnt print nested lvl objects.
You can do console.log(JSON.stringify(users)) or console.dir(users).

How we remove null error encounter in referencing node js mongodb

I have to use populate method for referencing my second collection. I have two collections one is levels and second child.
I have referenced to my level collection through child collection. For this, I use the populated method but it returns null.
This is node js code
function(){
var query = {'_id': result._id };
var params = 'usercurrLevelId';
childQuizInfo.findOne(query, params).populate({
path : 'usercurrLevelId',
model : 'Level',
select : '_id level_num age'
}).exec(function(err,levelinfo){
if(err) return next(err);
res.send(levelinfo);
});
}
This level schema
var LevelSchema = new Schema({
_id: { type: String },
age: { type: Number },
level_num: { type: Number },
min_score: { type: Number },
max_questions: { type: Number }
});
var Level = mongoose.model('Level', LevelSchema);
This is child schema
usercurrLevelId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Level',
index: true
}
This is the level stored in mongoDB
{
"_id" : ObjectId("57cb1ef8b0b05a2ce9b0c24b"),
"age" : 5,
"level_num" : 1,
"min_score" : 12,
"max_questions" : 30
}
{
"_id" : ObjectId("57cb1ef9b0b05a2ce9b0c24c"),
"age" : 5,
"level_num" : 2,
"min_score" : 15,
"max_questions" : 33
}
This is the child stored in mongoDB
{
"_id" : ObjectId("57cc0410d51045452644251b"),
"usercurrLevelId" : ObjectId("57cb1ef8b0b05a2ce9b0c24b")
}
And the output i get
{
"_id": "57cc0410d51045452644251b",
"usercurrLevelId": null,
"__v": 0
}
I using this node js query so that I get level_num and _id from my level schema using this referencing.

Mongoose DBrefs - Cast to ObjectId failed for value

I have a Team Schema holding details about teams, and a Match Schema to store these teams in. I am trying to make it so that the home/away teams in the Match Schema are references to the Team object. I have put my code below, I'm getting an error when saving the Team but I can't help but feel I have done something wrong with the Schema's or the saving of the Match. Can anyone help?
So far I have the following code:
Team.js extract
var Team = new Schema({
'key' : {
unique : true,
type : Number,
default: getId
},
'name' : { type : String,
validate : [validatePresenceOf, 'Team name is required'],
index : { unique : true }
}
});
module.exports.Schema = Team;
module.exports.Model = mongoose.model('Team', Team);
Match.js extract
var util = require('util');
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Team = require('../schemas/Team').Schema;
var Match = new Schema({
'key' : {
unique : true,
type : Number,
default: getId
},
'hometeam' : {
type : Schema.ObjectId,
ref : 'Team'
},
'awayteam' : {
type : Schema.ObjectId,
ref : 'Team'
}
});
module.exports = mongoose.model('Match', Match);
index.js
app.get('/match', function(req, res) {
var key = 1356136550152; // Reading
Team.findByKey(key, function(err, team) {
if(err) {
res.send("An error occured");
}
if(!team) {
res.send("The team does not exist");
}
var match = new Match();
match.hometeam = team;
match.save(function(err) {
if(err) {
util.log('Error while saving Match: ' + util.inspect(err));
res.send("An error occured whilst saving the match");
} else {
res.send("Saved the match");
}
});
});
});
ERROR:
Error while saving Match: { message: 'Cast to ObjectId failed for value "{ name: \'testTeam\',\n _id: 50d500663ca6067226000001,\n __v: 0,\n key: 1356136550152 }" at path "hometeam"',
name: 'CastError',
type: 'ObjectId',
value:
[ { name: 'testTeam',
_id: 50d500663ca6067226000001,
__v: 0,
key: 1356136550152 } ],
path: 'hometeam' }
Error with team._id
Error while saving Match: { [MongoError: E11000 duplicate key error index: testdb.matches.$team.name_1 dup key: { : null }]
name: 'MongoError',
err: 'E11000 duplicate key error index: testdb.matches.$team.name_1 dup key: { : null }',
code: 11000,
n: 0,
connectionId: 8,
ok: 1 }
db.matches.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"ns" : "testdb.matches",
"name" : "_id_"
},
{
"v" : 1,
"key" : {
"key" : 1
},
"unique" : true,
"ns" : "testdb.matches",
"name" : "key_1",
"background" : true,
"safe" : null
},
{
"v" : 1,
"key" : {
"team.key" : 1
},
"unique" : true,
"ns" : "testdb.matches",
"name" : "team.key_1",
"background" : true,
"safe" : null
}
]
In index.js it should be:
match.hometeam = team._id;
instead of:
match.hometeam = team;
UPDATE
Regarding the new error message, it looks like you have a unique index on the matches collection that refers to fields that don't exist. Drop it in the shell using:
db.matches.dropIndex('team.name_1')

Categories