I want to delete all elements from an array in my document..
I have an array of object id's
My model looks like this:
const TypeSchema = new mongoose.Schema({
ISOklasifikacija: { type: String, requred: false },
profilUIC: { type: String, requred: false },
certificateId: [
{
type: Schema.Types.ObjectId,
ref: "Certificates",
required: false,
},
],
});
My query for clearing the array is:
let type = await Type.findOneAndUpdate(
{
_id: req.params.typeId,
},
{
$set: { certificateId: [] },
},
{ multi: true }
);
console.log(type);
It nevers clear the array. In console I get: null and this id exists which I am passing in
Thanks for help
Related
i am trying to create items to specific id of collection using nodejs and mongoose but i am getting CastError which i shared below picture. So goal is, I binded items id in collection schema because collection has many items and when i create items to the specific id of collection i want to push them to items array in the collection schema.
ERROR
ITEMS ROUTE
itemRouter.post("/:collectionId", JWTAuthMiddleware, async (req, res, next) => {
const {name} = req.body
if (req.params.collectionId.length !== 24)
return next(createHttpError(400, "Invalid ID"));
const collection = await CollectionModal.findByIdAndUpdate(
req.params.collectionId,
{
$push : { items: { ...req.body, owner: req.user._id, id: uuidv4() } },
},
{ new: true }
);
if (!collection)
return next(
createHttpError(
400,
`The id ${req.params.collectionId} does not match any collections`
)
);
res.send(collection);
});
Collection schema
import mongoose from "mongoose";
const { Schema, model } = mongoose;
const collectionSchema = new Schema(
{
name: { type: String },
description: { type: String },
topic: { type: String },
image: { type: String },
additionalCustomFields: {
fieldNumber: { type: Number },
fieldName: { type: String },
fieldType: { type: String },
fieldChecked: { type: Boolean },
fieldDate: { type: Date },
},
owner: { type: Schema.Types.ObjectId, ref: "User" },
items: [{ type: Schema.Types.ObjectId, ref: "Item" }],
},
{ timestamps: true }
);
// collectionSchema.index({ "$**": "text" });
export default model("Collection", collectionSchema);
ITEM schema
import mongoose from "mongoose";
const { Schema, model } = mongoose;
const itemSchema = new Schema(
{
name: { type: String },
description: { type: String },
topic: { type: String },
image: { type: String },
comments: [
{
user: { type: Schema.Types.ObjectId, ref: "User", required: true },
text: { type: String },
},
],
tags: { type: String },
owner: { type: Schema.Types.ObjectId, ref: "User" },
likes: [{ type: Schema.Types.ObjectId, ref: "User" }],
collections: { type: Schema.Types.ObjectId, ref: "Collection" },
},
{ timestamps: true }
);
itemSchema.index({ "$**": "text" });
export default model("Item", itemSchema);
Are you sure that using referenced documents is the correct way to go here? Mongoose is complaining because you are trying to push whole objects to the "items" array, instead of ObjectIds of referenced documents.
You have 2 choices here:
1. use embedded documents
This way you can easily store objects directly to the items array, which does not allow you to store the Items in a seperate collection
2. first create Item documents, then push the reference to items array
In this case you have to first create the items in Item collection. Afterwards you can map the result to only ObjectIds and push these to items array of your collection document.
I was building a chat server, where i need to get the number of messages that is not marked as
seen . below is my schema
const ChatSchema = mongoose.Schema({
chatId: { type: String, required: true, unique: true },
messages: [
{
message: { type: String, required: true },
sendBy: { type: String, required: true },
sendTo: { type: String, required: true },
seen: { type: Boolean, default: false },
date: { type: Date, default: Date.now()}
},
],
})
I have tried the following code but it always returns 1
const unSeenCount=await Chat.find({ chatId: chatId },
{ messages : { $elemMatch : { seen : false } } })
console.log(`unseen count is ${unSeenCount.length}`);
The first object in the mongoose query is the filter which is what you were using in the second object. You can also use count to get the count returned by the filter query.
Try this:
const unSeenCount = await Chat.count({
messages: {
$elemMatch: {
seen: false
}
}
})
console.log(`unseen count is ${unSeenCount}`);
you can use the countDocuments Method
const unSeenCount=await Chat.countDocuments({{ chatId: chatId },
{ messages : { $elemMatch : { seen : false } } }})
console.log(`unseen count is ${unSeenCount}`);
I'm new to mongoDB and backend stuffs. I've a nested MongoDB model schema. I need to update, delete and add in that nested objects/array. How can I do that ?
How can I delete/add/update item from columns array and resume array.
const userSchema = new Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
},
columns: [
{
title: {
type: String,
required: true,
},
resumes: [
{
name: {
type: String,
required: true,
},
resume: {
type: String,
required: true,
},
},
],
},
],
});
const Users = mongoose.model('Users', userSchema);
This is my schema
To add new item to the columns array:
let newData = {title: "New Title", resumes: []}
let userData = await User.findByIdAndUpdate(userID, {
$push: {
columns: newData,
},
});
To add new item to the resumes array inside columns:
let newData = {name: "New Name", resume: "New Resume"}
let userData = await User.updateOne(
{
_id: mongoose.Types.ObjectId("60f54774761788cd80f56xxx"),
"columns._id": mongoose.Types.ObjectId("60f54774761788cd80f56xxx"),
},
{
$push: { "columns.$.resumes": newData },
}
);
Similarly, you can use $pull operator to remove an object from the array, and $(update) to update the element inside the array
I'm building a note taking app in which there can be as many nested notes inside one another as the user wants, Similar to folder and file structure expect here everything is a note, I have a note model inside it there is a sub_notes array, I want to be able to find a note whether it is a note at the top of the document or nested inside the sub_notes array, I'm passing the id of the note to which I want to add the next note, I have tried graphlookup but when I use the query it is returning an empty array
This is my Note model
const noteSchema = new Schema({
icon: {
type: String,
},
banner: {
type: String,
},
name: {
type: String,
required: true,
},
user_id: {
type: String,
required: true,
},
date: {
type: Date,
required: true,
default: Date.now,
},
sub_notes: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "notes",
},
],
content: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "blocks",
},
],
});
module.exports = Note = mongoose.model("notes", noteSchema);
This is the query I'm using to find the nested note, The path is a dot seperated string with ids of the notes & the note is the actual note object with the name and other data.
So for ex:
The note
{
id: "123123123",
sub_notes: [{
id: "xyz"
}]
}
So the path here will be 123123123.xyz
var {
note,
path
} = req.body;
var newPath = path.split(".");
const parentNote = Note.findById(newPath[0]);
newPath.splice(0, 1);
console.log(newPath[newPath.length - 1]);
Note.aggregate([{
$match: {
$id: newPath[newPath.length - 1]
}
},
{
$graphLookup: {
from: "notes",
startWith: "$id",
connectFromField: "sub_notes",
connectToField: "id",
depthField: "level",
as: "sub_notes",
},
}
]).exec((err, notes) => {
console.log(notes);
});
I have 1 main collection and 1 collection with a ref to the main one. Code looks like :
// Ref schema
const onlineSchema = mongoose.Schema({
_id: {
type: Number,
ref: 'Player',
unique: true
}
}, {
timestamps: true
});
//main schema
const playerSchema = mongoose.Schema({
_id: { // User ID
type: Number,
required: true,
unique: true,
default: 0
},
firstname: {
type: String
},
name: {
type: String,
required: true
},
lastname: {
type: String
},
barfoo: {
type: Boolean
}
...
})
I populate it with this code :
var baz = bar;
...
Online.find().populate({
path: '_id',
match: {
[ baz + 'foo']: true
}
}).exec(function(err, online) {
if (err) {
winston.error(err);
} else {
winston.error(util.inspect(online, {
showHidden: false,
depth: null
}));
}
});
If there are 10 elements in online and only 7 match [ baz + 'foo']: true I get 7 proper arrays and 3 empty arrays that look like this:
{ updatedAt: 2016-12-23T18:00:32.725Z,
createdAt: 2016-12-23T18:00:32.725Z,
_id: null,
__v: 0 },
Why is this happening and how to I filter the final result so it only shows the matching elements?
I can use filter to remove the null arrays after I get the result but I'd like to know how to prevent the the query from passing null arrays in the first place.
Why is this happening ?
This is happening because you get all the documents with Online.find() but the player will be populated only for records that match your condition. Your match is for the populate, not for the find() query.
How do I filter the final result so it only shows the matching
elements ?
You cant find a nested elements of a referenced collections since there is no join in MongoDB. But you can :
keep your schema and use aggregation with $lookup :
Online.aggregate(
[{
$lookup: {
from: "players",
localField: "_id",
foreignField: "_id",
as: "players"
}
}, {
$unwind: "$players"
}, {
$match: {
'players.barfoo': true
}
}],
function(err, result) {
console.log(result);
});
change your schema to include Player as a subdocument :
const playerSchema = new mongoose.Schema({
//...
});
const onlineSchema = new mongoose.Schema({
player: playerSchema
}, {
timestamps: true
});
var Online = mongoose.model('Online', onlineSchema);
Online.find({'player.barfoo':true}).exec(function(err, online) {
console.log(online);
});
Dont make _id the reference of another schema, instead make another field name player and give reference through that.
const onlineSchema = mongoose.Schema({
player: {
type: Number,
ref: 'Player',
unique: true
}
}, {
timestamps: true
});
Population:
Online.find().populate({
path: 'player',
match: {
[ baz + 'foo']: true
}
}).exec(...);
dont use _id to ref field.. because its default filed in mongoDB to create index unique.. change you're field name