I want to return one index's object of the array,
but when I query, It returns to me that all of the documents.
This is my Schema(userTb)
const userTbSchema = new Schema({
_id: mongoose.Schema.Types.ObjectId,
userId: String,
gender: String
}
And this is my another Schema(product)
const productSchema = new Schema({
_id: mongoose.Schema.Types.ObjectId,
product: String,
userTbId: { type: mongoose.Schema.Types.ObjectId, ref: "userTb", required: true },
}
And They are in another js file.
This is the result of the query of my Schema(product) don't use Populate.
{
"_id": "5fc4c13f32ab3174acb01234",
"product": "watch",
"userTbId": "5fc4c13f32ab3174acb08540"
},
{
"_id": "5fc4c2d6b3a2a054d4dc1235",
"userId": "car",
"userTbId": "5fc4c2d6b3a2a054d4dc462c"
}
And This is the result of the query of my Schema(product) when I using Populate.
{
"_id": "5fc4c13f32ab3174acb01234",
"product": "watch",
"userTbId": {
"_id": "5fc4c13f32ab3174acb08540",
"userId": "go05111",
"gender": "male"
}
},
{
"_id": "5fc4c2d6b3a2a054d4dc1235",
"userId": "car",
"userTbId": {
"_id": "5fc4c2d6b3a2a054d4dc462c",
"userId": "Chips",
"gender": "female"
}
}
I want to get the only { "gender" : "male" } object in proudct, like...
{
"_id": "5fc4c13f32ab3174acb01234",
"product": "watch",
"userTbId": {
"_id": "5fc4c13f32ab3174acb08540",
"userId": "go05111",
"gender": "male"
}
}
so I query like this
router.get('/:gender', (req, res, next) => {
Product.find({
"userTbId.gender": req.params.gender
})
.populate({
path: 'userTbId',
match: {
userId: req.params.userId
}
})
.exec()
.then(docs => {
res.status(200).json({
docs
});
})
.catch(err => {
res.status(500).json({
error: err
});
});
});
but the result is nothing returned.
I think the userTbId is ObjectId, so even if populate() is used, the value does not appear when find() is used.
I tried a few different ways, but it didn't work that I want.
how can I fix it in mongoose?
would you please help me?
In mongoose, populate will execute on the result set from the find query.
In your Product schema userTbId is an object id and it will not have the gender property unless it gets populated. To achieve your goal only by using mongoose, you can write a query like below. First you need to find all the userTbIds for your gender and userId. Then query your Product schema for the returned userTbIds. Corrections and optimisations are welcome.
router.get('/:gender', (req, res, next) => {
userTbId.find({
"gender": req.params.gender,
"userId": req.params.userId
}).exec()
.then(docs => {
let ids = docs.map(doc => doc.id);
Product.find({
"userTbId": {$in:ids}
})
.populate({
path: 'userTbId'
})
.exec()
.then(docs => {
res.status(200).json({
docs
});
})
.catch(err => {
res.status(500).json({
error: err
});
});
})
.catch(err => {
res.status(500).json({
error: err
});
});
});
Related
I want to return one index's object of the array,
but when I query, It returns to me that all of the documents.
This is my Schema(userTb)
const userTbSchema = new Schema({
_id: mongoose.Schema.Types.ObjectId,
userId: String,
folders: [
{
folderTitle: String,
}
]
}
and this is the result of the query of my Schema(userTb).
{
"_id": "5fc4c13f32ab3174acb08540",
"userId": "go05111",
"folders": [
{
"_id": "5fb7b0473fddab615456b166",
"folderTitle": "first-go"
},
{
"_id": "5fb7b0473fddab615456b16b",
"folderTitle": "second-go"
}
]
}
I want to get the only { "folderTitle" : "first-go" } folder's object, like...
{
"_id": "5fb7b0473fddab615456b166",
"folderTitle": "first-go"
}
so I query like this
router.get('/folder/:folderId', (req, res, next) => {
UserTb.find({ folders : { "$elemMatch" : { _id : req.params.folderId} } })
.exec()
.then(docs => {
res.status(200).json({
docs
});
})
.catch(err => {
res.status(500).json({
error: err
});
});
});
but the result is nothing changed.
I tried a few different ways, but it didn't work out.
how can I fix it?
please help me...
Try this (live version):
UserTb.aggregate({
$match: {
"folders._id": req.params.folderId }
},
{
$project: {
folders: {
$filter: {
input: "$folders",
as: "f",
cond: {
$eq: [
"$$f.folderTitle",
"first-go"
]
}
}
},
_id: 0
}
})
It will retrieve folders:[{...}] this will be easy to tackle using JS, and quicker.
Mechanism
Match only documents containing _id:folderId
project only the inner document
I am building an API to store friends names for a game, I have built the API to receive the post request as so :
exports.addFriends = async (req, res) => {
try {
console.log('hit');
console.log(req.body.friendNames);
const addUser = await User.updateOne(
{ uniqueid: req.body.uniqueid },
{ $push: { friendNames: [req.body.friendNames] } }
);
res.json({
addUser
});
} catch (error) {
console.log(error);
}
};
ad the post request as
const friends = await axios.post('/api/v1/users/add/friends', {
uniqueId: this.uniqueid,
friendNames: [
{
userName: 'test',
region: 'euw'
}
]
});
My API is being hit as a see the logs, but no record is made. My User Schema is as so
const userSchema = new mongoose.Schema({
uniqueid: {
type: String,
required: true,
trim: true
},
summonerName: {
type: String
},
friendNames: [
{
userName: String,
region: String
}
]
});
I get no error and the request seems to go through, but no records are added. Any ideas?
$push is used to add one element to the array. But using the $each array update operator, we can push an array of items.
Also, I used findOneAndUpdate with new:true option to retrieve the updated document, because updateOne doesn't return the updated document.
exports.addFriends = async (req, res) => {
try {
console.log(req.body.friendNames);
const addUser = await User.findOneAndUpdate(
{ uniqueid: req.body.uniqueid },
{ $push: { friendNames: { $each: req.body.friendNames } } },
{ new: true }
);
res.json({ addUser });
} catch (error) {
console.log(error);
res.status(500).send("Something went wrong");
}
}
Let's say we have this existing document:
{
"_id": "5e31c749f26d5f242c69f3aa",
"uniqueid": "uniqueid1",
"summonerName": "John",
"friendNames": [
{
"_id": "5e31c749f26d5f242c69f3ab",
"userName": "Max",
"region": "Germany"
}
],
"__v": 0
}
Let's send a request to the controller with this request body:
{
"uniqueid": "uniqueid1",
"friendNames": [
{
"userName": "Andrew",
"region": "England"
},
{
"userName": "Smith",
"region": "USA"
}
]
}
The response will be like this:
{
"addUser": {
"_id": "5e31c749f26d5f242c69f3aa",
"uniqueid": "uniqueid1",
"summonerName": "John",
"friendNames": [
{
"_id": "5e31c749f26d5f242c69f3ab",
"userName": "Max",
"region": "Germany"
},
{
"_id": "5e31c763f26d5f242c69f3ad",
"userName": "Andrew",
"region": "England"
},
{
"_id": "5e31c763f26d5f242c69f3ac",
"userName": "Smith",
"region": "USA"
}
],
"__v": 0
}
}
Hello I am trying to delete pushed (data) _id from a document array, but I am getting no response while executing.
Also, since it is a relational _id which I am trying to delete. How can I delete from the collection it is actually stored ?
here is my delete route:-
router.delete('/userDelete/:userId', checkAuth , (req, res, next) =>{
if(req.userData.role2 === 'admin') {
Admin.findOneAndDelete({_id: req.params.userId},{ $pull: { 'admins.users': {_id: req.params._id}}},{new: true})
.exec()
.then(result => {
res.status(200).send(["Deleted"]);
})
.catch(err =>{
if (err.code == 500)
res.status(500).send(["Didn't get deleted"]);
else
return next(err);
});
}else{
res.send(["Unauthorized. Not deleted"]);
}
});
This is the nested object looks like :-
{
"admins": {
"users": [
"5d0364048db4957100f33fea" //<===want to delete this relational id
],
"email": "1cf1eede89#himail.online",
"password": "$2a$10$vHyGxX9P.t0/ybKcmIzkc.ZCX18oHaVnvTgJIWA2gTNzJ3TCdXS4a",
"_id": "5d0339d5b4b28b6ddff06802",
"companyName": "GH",
"__v": 0
}
This is my controller :-
var admin = new Admin();
admin.companyName = req.body.companyName;
admin.admins = {
email : req.body.email,
password: req.body.password,
users : []
};
Is is also possible to delete records from each and every collections where particular _id data is located ?
You need to find the Document and update,
Data
{
"_id" : "5d0339d5b4b28b6ddff06802",
"admins" : {
"users" : [
"5d0364048db4957100f33fea"
]
}
}
Query
db.users.updateOne(
{ _id: req.params.userId },
{
$pull: {
"admins.users": req.params._id
}
}
);
Result
{
"_id" : "5d0339d5b4b28b6ddff06802",
"admins" : {
"users" : [ ]
}
}
I'm trying to get a subdocument (nested in array) by its id, but I still get the whole document.
router.get("/book/:libraryid/:bookid", (req, res) => {
Library.findOne({ _id: req.params.libraryid, "book._id": req.params.bookid})
.then(result => {
console.log(result); //shows all subdocument
});
});
How can I just pick out the subdocument with its id?
Schema:
{
"_id": {
"$oid": "12345"
},
"libaryName": "A random libary",
"Books": [
{
"_id": {
"$oid": "1"
}
"bookTitle": "Example",
"TotalPages": "500"
},
{
"_id": {
"$oid": "2"
}
"bookTitle": "Delete Me",
"TotalPages": "400"
}
]
}
Use the following and it should return you the document with only filtered book based on bookId.
router.get("/book/:libraryid/:bookid", (req, res) => {
Library.findOne({ _id: req.params.libraryid}, {"books": {"$elemMatch": {_id: req.params.bookid}}})
.then(result => {
console.log(result); //shows all subdocument
});
});
So far I can only manage to delete the first id (in this case the id with "12345").
Im trying to delete the row with id 2 within books-array
Libary Table:
{
"_id": {
"$oid": "12345"
},
"libaryName": "A random libary",
"Books": [
{
"_id": {
"$oid": "1"
}
"bookTitle": "Example",
"TotalPages": "500"
},
{
"_id": {
"$oid": "2"
}
"bookTitle": "Delete Me",
"TotalPages": "400"
}
]
}
My delete code:
router.delete('/:id', (req, res) => {
Libary.remove({ _id: req.params.id })
.then(() => {
//redirect
});
});
How can I reach and delete the book row where the id is 2?
You need to use $pull opertator
router.delete('/:id', (req, res) => {
Libary.update({ _id: req.params.id }, //This is the Id of library Document
{ $pull: { "Books": {"_id":2) } } }) // This will be the Id of book to be deleted
.then(() => {
//redirect
});
});
Hope it helps.
You need to use $pull:
Library.update(
{ },
{ $pull: { Books: { _id: 2 } } }
)