I have a mongoose schema with an array of objects...
Im trying to get only matching userID in the array, however the array return all the users if there is even one match.
I have the following on node js
app.get("/myanswers/:id", async (req, res) => {
try {
const q = await posts.find(
{ "postAnswer.userID": req.params.id },
"postAnswer.answer postAnswer._id postAnswer.user postAnswer.userID"
);
res.json(q);
} catch (error) {
res.send(error);
}
});
and i get this result:
[
{
"_id": "6074f2648e9f41497438b37a",
"postAnswer": [
{
"_id": "6074f3858e9f41497438b37b",
"userID": "60579272980cb93ea8a91140",
"user": "admin",
"answer": "Kakashi 🐱👤"
}
]
},
{
"_id": "6074f4768e9f41497438b37c",
"postAnswer": [
{
"_id": "6074f5338e9f41497438b37e",
"userID": "6074f4f98e9f41497438b37d",
"user": "barrym",
"answer": "here's the correct sequence. table, add row table headers close row. add row add table data close row close table."
},
{
"_id": "6074f5808e9f41497438b37f",
"userID": "60579272980cb93ea8a91140",
"user": "admin",
"answer": "with TH and TD!"
}
]
}
]
i only want exact match so user barrym shouldn't appear
Demo - https://mongoplayground.net/p/3BV58F3GiS4
Use $ (projection)
Note:- limits the contents of an to return the first element
The positional $ operator limits the contents of an to return the first element that matches the query condition on the array.
db.collection.find(
{ "postAnswer.userID": "6074f4f98e9f41497438b37d"},
{ "postAnswer.$": 1}
)
Related
I am writing REST API in NodeJS with MongoDB. Structure of the database is:
[
{
"_id": "12345",
"name": "Meal name",
"category": "dessert",
"area": "british",
"imageUrl": "https.image.jpg",
"instructions": "some instructions...",
"ingredients": [
{
"name": "salt",
"measure": "1g"
},
{
"name": "chicken",
"measure": "1"
},
{
"name": "butter",
"measure": "90g"
}, ...
]
}, ...
]
I can write a route to get data which meet one condition,
i.e.:
//getting all, when category = :category
router.get('/meals/category=:category', async (req, res) => {
try {
const meals = await Meal.find({category: req.params.category})
res.json(meals)
} catch (err) {
res.status(500).json({ message: err.message })
}
})
Here, route
'meals/category=vegetarian'
get all data with category = vegetarian.
However, I want to have route, which will filter all data by parameters: category, area, ingredients.
For example:
meals/ingredients=salt,pepper&category=dessert&area=american
should return all data, which contains salt and pepper in array, and category = dessert.
another example:
meals/area=american&category=dessert
should return all data, where area=american and category=dessert
How can I write the router.get() method to achieve that?
Document in mongodb collection 'users' is
{
"$oid": "5e612272bcb362513824ff9b",
"name": "abcd",
"email": "test#test.com",
"cart": {
"items": [{
"productId": {
"$oid": "5e614367cae25319c4388288"
},
"quantity": {
"$numberInt": "1"
}
}]
}
}
For a particular users._id and a productId in cart.items, I need to increase the quantity by 1
My nodejs code is
IncrCartItem(prodId){
const db=getDb()
return db
.collection('users').
updateOne({_id: new mongodb.ObjectId(this._id),'this.cart.items.productId': new mongodb.ObjectId(prodId)},{$inc : {'this.cart.items.quantity':1}})
}
Is the query right for checking multiple conditions in updateOne()??
You're kinda there, to "and" them all together you just keep appending them, however the field is wrong and you need to use the positional operator ($) - https://docs.mongodb.com/manual/reference/operator/update/positional/
const filter = {
_id: new mongodb.ObjectId(this._id),
'cart.items.productId': new mongodb.ObjectId(prodId)
};
const update = {
$inc : { 'this.cart.items.$.quantity': 1 }
};
IncrCartItem(prodId){
const db=getDb()
return db
.collection('users').
updateOne(filter,update)
}
I have a data like in mongodb collection name property.
{
"_id": "593a3d828e2ef100d1496e77",
"feature_type": "house",
"features": [
{
"name": "h1"
},
{
"name": "h2"
}
]
}
I want only
[
{
"name": "h1"
},
{
"name": "h2"
}
]
as result i tried this by
req.db.collection('FeatureSettings').findOne({feature_type: req.params.feature_type}, {features: 1});
this give
{
"_id": "593a3d828e2ef100d1496e77",
"features": [
{
"name": "Hotel"
},
{
"name": "Apartment"
}
]
}
what can i do to get result as given above.
You have to exclude the _id from your projection like here:
req.db.collection('FeatureSettings').findOne({feature_type: req.params.feature_type}, {features: 1, _id:0});
Assuming you're using something like mongoose that returns promises, you could use the result of the query
return req.db.collection('FeatureSettings')
.findOne({feature_type: req.params.feature_type}, {features: 1})
.then((result) => {
return result.features;
});
You can try this to return only features array values.
req.db.collection('FeatureSettings')
.findOne({feature_type: req.params.feature_type}, {features:1, _id:0}).features;
OR
// if you use mongoose can use
return req.db.collection('FeatureSettings')
.findOne({feature_type: req.params.feature_type}, {features:1, _id:0})
.exec()
.then((result) => {
return result.features;
});
how to get the specific message by _id.
I have a database schema as shown below:
{
"_id": ObjectID("5846eedaf0b51ed02ed846e2"),
"name": "conversation name"
"messages": [
{
"_id": ObjectID("584820a96866b6283361a4b9"),
"content": "hello",
"status": 0,
"type": 0
},
{
"_id": ObjectID("584820d56866b6283361a4ba"),
"content": "voices/1481122005696.mp3",
"status": 0,
"type": 3
}
]
}
db.collection.find({}, {
'messages': {
$elemMatch: {
'_id': ObjectId("584820a96866b6283361a4b9")
}
}
})
This will match on all documents in your collection, and return the matching array subfield in the projection. See the link posted in Yogesh's comment.
Since you tagged mongoose, I put it like this, but the query syntax is valid because is part of mongoDB query syntax:
Conversation.findOne({
"messages._id": "584820a96866b6283361a4b9"
}, function(err, document){
if (err) {
console.log(err)
return
}
var message = document.messages.id("584820a96866b6283361a4b9")
})
The finOne() method will return the full parent document with all the messages (subdocuments) and other properties. You then need to filter out the subdocument. Mongoose provides a way to do this easily with: document.messages.id("584820a96866b6283361a4b9") where document would be the data object passed to the find callback
See:
Match a Field Without Specifying Array Index on
https://docs.mongodb.com/v3.2/tutorial/query-documents/#query-on-arrays
I have a document with the array of objects and one object contains multiple objects I want to update inner object with $set but didn't get any luck.
can anybody give me any hint so that I can resolve it?.
This is my object:
{
"_id": ObjectId("56fbfafdf86fa6161911d104"),
"site": "xyz",
"adsPerCategory": NumberInt(2),
"sampledAt": ISODate("2016-03-30T16:12:45.138+0000"),
"items": [
{
"id": "4563873",
"content": {
"title": "WATER DISTILLERS",
"body": "Perfect to save money.",
}
},
{
"id": "4563s23232873",
"content": {
"title": "Cola water",
"body": "Perfect for body.",
}
}
]
}
I want to update body.
for now, I have given single object but it can be multiple.
Here what I tried
models.Sample.update(
{
_id: samples._id
},
'$set': {
'items.0.content.body': body.description
},
function(err, numAffected) {
console.log(err);
console.log('Affected....', numAffected);
}
);
It's working fine if I put 0 but I want to make it dynamic.
Like 'items.index.content.body': body.description
Thank You.
I think you can do something like this.
models.Sample.find({ _id: ObjectId(samples._id) })
.forEach(function (doc) {
doc.items.forEach(function (element, index, array) {
items[index].content.body = body.description;
});
models.Sample.save(doc);
});