I'm trying to delete a project object from an array.
projects:
{
_id : ...,
userName: milad ,
projets : [
{ .. projectId, pName, location .... A },
{ .. projectId, pName, location .... B },
{ .. projectId, pName, location .... C },
]
}
How to delete Project B in MongoDB?
projects after remove Project B:
{
_id : ...,
userName: milad ,
projets : [
{ .. projectId, pName, location .... A },
{ .. projectId, pName, location .... C },
]
}
If you have received a document from your database, you can remove an object from your array - based on the location - in such a way:
const doc = {
_id: '507f191e810c19729de860e0',
userName: 'milad',
projects: [
{ _id: '507f191e810c19729de860ea', pName: 'projectA', location: 'a' },
{ _id: '507f191e810c19729de860eb', pName: 'projectB', location: 'b' },
{ _id: '507f191e810c19729de860ec', pName: 'projectC', location: 'c' }
]
}
// remove project b (one method, there are many more)
doc.projects = doc.projects.filter((project) => project.location !== 'b');
After the filter process you have to save it back to your mongoDB:
Mongoose: (example)
await doc.save();
another answer
db.collection('Profile').updateOne({ userName: username,
"Projects.projectId": projectId }, { $pull: { 'Projects': { projectId: projectId } }})
}
Related
My Mongo schema looks like this,
I want to update a flashcard object located in an array of flashcard also located in an array of subject.
const classrooms = new mongoose.Schema({
name: String,
year: String,
student: [
{
firstname: String,
lastname: String,
mail: String,
userId: String,
}
],
subject: [
{
subjectId: String,
flashcard: [
{
title: String,
tag: []
}
]
}
]
});
What I am doing is
const flashcard = await classroomModel.findOneAndUpdate({
_id : classroomId,
"subject" : {
"subjectId" : subjectId,
"subject.flashcard" : {
"_id" : flashcardId
}
},
"$set" : {
"flashcard.title" : "new title"
}
})
But this is deleting all flashcards located inside an object.
Any help would be appreciated.
You need arrayFilters to specify the (to-be-updated) flashcard document that meets the criteria for subject and flashcard.
db.collection.update({
_id: 1//classroomId,
},
{
"$set": {
"subject.$[subject].flashcard.$[flashcard].title": "new title"
}
},
{
arrayFilters: [
{
"subject.subjectId": 1//subjectId
},
{
"flashcard._id": 1//flashcardId
}
]
})
Sample Mongo Playground
Although i accepted #yong shun which is the best approach, another way to do it in case you don't like mongoose syntax :
const classroom = await classroomModel.findOne(
{
_id: 1 //classroomId,
},
)
const subject = classroom.subject.find(
(currentSubject: any) => {
return currentSubject.subjectId == 1 //subjectId
}
)
const flashcard = subject.flashcard.find(
(currentFlashcard: any) => {
return currentFlashcard._id == 1 //flashcardId
}
)
flashcard.title = "my new title";
await classroomModel.updateOne(classroom);
I am trying to make a query to find documents depending on another document in the same collection as below.
The first one finds the user and the second one finds the data by using that user data received. But I want to do it with one query like join in SQL
This is schema
var ConnectionSchema = new Schema({
socketId: {
type: String,
require: true
},
location: {
type: [Number],
index: '2dsphere'
},
user: { type: Schema.ObjectId, ref: "User" },
date: {
type: Date,
require: true,
default: new Date()
}
});
// queries
return mongoose.model("Connection").findOne({ user: userId }).populate("user").then(usr => {
return mongoose.model("Connection").find({
location: {
$near: {
$maxDistance: config.searchDistance,
$geometry: { type: Number, coordinates: usr.location }
}
},
user: { $ne: userId },
});
});
Is there any way to do that with a just single query?
Thanks.
yes there is a way you can do like this
return mongoose.model("Connection").findOne({ user: userId })
.populate("user" ,
match : {$and : [{location: {
$near: {
$maxDistance: config.searchDistance,
$geometry: { type: Number, coordinates: usr.location }
}
}},
{user: { $ne: userId }}]})
.then(usr => {
// perform your action
});
I have this type of mongoose schema shown below:
const brandSchema = mongoose.Schema({
brandname: {
type: [],
require: true,
},
frequency: {
type: [
{brand1 : []},
{brand2 : []}
],
},
date: {
type: [],
}
})
I want to be able to add two brandname to it at the to, then id find the brand name then keep appending values to the array later. Is there a way I can do this?
You can use $push operator in findOneAndUpdate method. Example:
Model.findOneAndUpdate(
{ "_id": model._id, "projects._id": id },
{$push: {
[`projects.$.path.${version}`]: {path: `${sha256}.${ext}`}
}},
(err, doc) => {
if (err) {
res.status(500).json({status: 'error'});
}
}
);
In users.js:
var mongoose = require('mongoose');
var User = mongoose.model('user', {
username: {
type: String,
required: true,
unique: true,
lowercase: true,
},
tasks: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Tasks',
}],
});
module.exports = User;
I then add a newUser named user1 and save to mongo.
The mongo doc looks like:
{
"_id" : ObjectId("574fb94f6a1e7d1826c16058"),
"username" : "user1",
"tasks" : [ ],
"__v" : 0
}
then try to fetch the document and it works fine in this handler:
In handlerA.js:
var User = require('../models/users.js');
module.exports.getUser = function(req, res){
User.findOne({username: "user1"}, function(err, data){
if(err){
console.log('getUser err', err);
res.send('ERROR')
} else {
console.log('getUser fx success = ', err, data);
res.send(data)
}
});
};
The result of the console.log:
getUser fx success = null { tasks: [], __v: 0, username: 'user1', _id: 574fb94f6a1e7d1826c16058 }
but same code fails in this other handler in a separate file.
In handlerB.js:
var User = require('../models/users.js');
module.exports.addStuff = function(req, res){
User.findOne({username: "user1"}, function(err, data){
if(err){
console.log('addStuff err', err);
res.send('ERROR')
} else {
console.log('addStuff fx success =', err, data);
res.send(data)
}
});
};
The result of the console.log:
addStuff fx success null null
Tried....and Failed....
I also tried this other solution from this question: Mongoose query return null
Mongoose pluralizes model names so it's running find on the "blogposts" collection instead of "blogpost". That said, your query in the mongo shell is on the "blogmodel" collection. In that case:
var BlogModel = mongoose.Model("BlogModel", ..)
or pass the collection name as the third param:
var BlogModel = mongoose.model("BlogPost", schema, "blogmodel")
This solution results in handlerA.js returning a null document as well as handlerB.js.
Thanks for your time. Much appreciated.
ADDENDUM.
I ran a find({}) under both the User and the Tasks models in handlerB.js
The returned document IN BOTH cases is based on the Tasks model.
see console.logs below for User.find({}) and Tasks.find({})
the err is the null value then the data.
How badly have I broken things? How can a Model.find return data that is not even in the model?
User.find({},funtion(err, data) ____________________
console.log of err then data
null
[ { subtasks: [],
team: [ [Object] ],
__v: 0,
maintask: '1',
_id: 574fce63d744cba421f750c1
},
{ subtasks: [],
team: [ [Object] ],
__v: 0,
maintask: '2',
_id: 574fce65d744cba421f750c2
}
]
Tasks.find({},function(err, data) ___________________
console.log of err then data
null
[ { subtasks: [],
team: [ [Object] ],
__v: 0,
maintask: '1',
_id: 574fce63d744cba421f750c1 },
{ subtasks: [],
team: [ [Object] ],
__v: 0,
maintask: '2',
_id: 574fce65d744cba421f750c2
},
]
This is the Tasks model...
tasks.js
var mongoose = require('mongoose');
var subtaskSchema = new mongoose.Schema({
subtask: {
type: String,
},
team: {
type: Array,
'defualt': [],
},
done: {
type: Boolean,
'defualt': false,
},
});
var Tasks = mongoose.model('tasks', {
maintask: {
type: String,
},
subtasks: {
type: [subtaskSchema],
},
team: {
type: Array,
'defualt': [],
},
done: {
type: Boolean,
'defualt': false,
},
});
module.exports = Tasks;
The mongoose docs suggest to define a model like so, did you try this?
var schema = new mongoose.Schema({ name: 'string', size: 'string' });
var Tank = mongoose.model('Tank', schema);
In my novice skill to Mongodb and Mongoose, I seem to be failing miserably at this fundamental task.
I have a bounded array of 10 elements. A user can only have 10 pets, so I figured to make it bounded with set fields and empty values was the best way.
The pets array values are blank at the time of creation, because the user can add pets as they go along. When I look in mongo console, the pets array is unbounded with no fields. I also can't add values to the array.
Mongoose Schema:
var userSchema = new Schema({
firstName: { type: String, required: true },
lastName: { type: String, required: true },
username: { type: String, required: true, unique: true },
location: String,
created_at: Date,
pets: [
{ "pet0": {} },
{ "pet1": {} },
{ "pet2": {} },
{ "pet3": {} },
{ "pet4": {} },
{ "pet5": {} },
{ "pet6": {} },
{ "pet7": {} },
{ "pet8": {} },
{ "pet9": {} }
]
});
mongodb:
{ "_id" : ObjectId("56a3e324bdebcf801c1ca224"), "firstName" : "bob", "lastName" : "smith", "username" : "bob123", "pets" : [ ], "__v" : 0 }
When modifying the array:
UserModel.findOne({ firstName: "bob" }, 'pets', function(err, user) {
user.pets[0] = { "name": "felix", "type": "cat" }
user.save(function(err) { console.log(err); console.log('saved')});
});
output:
Mongoose: users.findOne({ firstName: 'bob' }) { fields: { pets: 1 } }
null
/home/one/github/foo/node_modules/mongoose/lib/schema/documentarray.js:100
doc.validate({ __noPromise: true }, function(err) {
^
TypeError: undefined is not a function
at /home/one/github/foo/node_modules/mongoose/lib/schema/documentarray.js:100:11
at DocumentArray.SchemaType.doValidate (/home/one/github/foo/node_modules/mongoose/lib/schematype.js:654:22)
at DocumentArray.doValidate (/home/one/github/foo/node_modules/mongoose/lib/schema/documentarray.js:78:35)
at /home/one/github/foo/node_modules/mongoose/lib/document.js:1156:9
at process._tickCallback (node.js:355:11)
MongoDB allows you to limit the number of elements in an array. This feature has also been implemented in Mongoose as part of an .update query. The steps for adding an element to an array and limiting its size are as follows:
Push the element(s) into the array.
Slice the array.
This snippet of code explains how to do this using Mongoose:
UserModel.findOne({ firstName: "bob" }, function(err, user) {
UserModel.update(user, {
$push: {
pets: {
$each: [{ name: "felix", type: "cat" }],
$slice: -10
}
}
}, function(err, numAffected) {
if (err) console.log(err);
console.log('updated');
});
});