Node mongoose embedded document array - mongodb

I have my sample userSchema here:
{
"_id": objectId("6092076ba811e50b565497ec"),
"username": "test#gmail.com",
"address_book": [{
"_id": objectId("6092b1120f7e370b954a2708"),
"address": "address1",
"address2": "address2",
}, {
"_id": objectId("6093edcb88796b0a5eba19a3"),
"address": "test1",
"address2": "test2",
}]
}
Can I find user by
objectId("6092076ba811e50b565497ec") and address_book._id object("6093edcb88796b0a5eba19a3")
and it return only the address_book that I selected? my expected return data should look like this
{
"_id": objectId("6092076ba811e50b565497ec"),
"username": "test#gmail.com",
"address_book": {
"_id": objectId("6093edcb88796b0a5eba19a3"),
"address": "test1",
"address2": "test2",
}
}
here is my sample function
let user = [];
await User.findOne({
_id: id,
"address_book._id": address_id,
})
.then((result) => {
console.log(result);
user = result;
})
.catch((err) => console.log(err));
return user;
with this I get all address_book
and also can is there and updateOrCreate function by address_book._id?
Thank you in advance.

You can use aggregation operators in find method starting from MongoDB 4.4,
$filter to iterate loop of address_book array and match _id condition
$first to select first element from above filtered result
await User.findOne({
_id: id,
"address_book._id": address_id
},
{
username: 1,
address_book: {
$first: {
$filter: {
input: "$address_book",
cond: { $eq: ["$$this._id", mongoose.Types.ObjectId(address_id)] }
}
}
}
})
Playground

elemMatch is what you are looking for according to me. elemMatch for projection not just the match.
db.<collection name>.find({
< search using elem match >
}, {
games: {
$elemMatch: {
//put your projection piece here, whatever selective what you want, check the example on documentation
score: {
$gt: 5
}
}
},
//anything else that you would want apart from within array projection
})
Update :
Data
[
{
"_id": "6092076ba811e50b565497ec",
"username": "test#gmail.com",
"address_book": [
{
"_id": "6092b1120f7e370b954a2708",
"address": "address1",
"address2": "address2",
},
{
"_id": "6093edcb88796b0a5eba19a3",
"address": "test1",
"address2": "test2",
}
]
}
]
Command
db.collection.find({},
{
address_book: {
$elemMatch: {
address: "test1"
}
}
})
Result
[
{
"_id": "6092076ba811e50b565497ec",
"address_book": [
{
"_id": "6093edcb88796b0a5eba19a3",
"address": "test1",
"address2": "test2"
}
]
}
]
Playground

Related

Select and filter MongoDB subdocument array list

I am trying to select document with filter userInteractions array. I need to remove item where userdId = "633eb753c8e3d3fd71d1c254" and return document as result. It is easy way to approach it with MongoDB query?
https://mongoplayground.net/p/2UHw52QJkYu
Example of JSON document:
{
"_id": {
"$oid": "633c25965034208db76cfb1e"
},
"email": "test#test.com",
"users": [
{
"type": "person",
"isActive": true,
"userInteractions": [
{
"userId": {
"$oid": "633eb753c8e3d3fd71d1c254"
},
"firstName": "Tom",
"lastName": "Hawkins",
},
{
"userId": {
"$oid": "633eb753c8e3d3fd71d1c222"
},
"firstName": "Melan",
"lastName": "Key",
},
{
"userId": {
"$oid": "633eb753c8e3d3fd71d1c259"
},
"firstName": "Ken",
"lastName": "Olibar",
},
]
}
]
}
Expecting output:
{
"_id": {
"$oid": "633c25965034208db76cfb1e"
},
"email": "test#test.com",
"users": [
{
"type": "person",
"isActive": true,
"userInteractions": [
{
"userId": {
"$oid": "633eb753c8e3d3fd71d1c222"
},
"firstName": "Melan",
"lastName": "Key",
},
{
"userId": {
"$oid": "633eb753c8e3d3fd71d1c259"
},
"firstName": "Ken",
"lastName": "Olibar",
},
]
}
]
}
$set - Set users field.
1.1. $map - Iterate the users array and return a new array.
1.1.1. $mergeObjects - Merge the current iterated document and the document from the result 1.1.1.1.
1.1.1.1. $filter - Filter the document(s) from the userInteractions array from the current iterated document.
db.collection.aggregate([
{
$set: {
users: {
$map: {
input: "$users",
as: "user",
in: {
$mergeObjects: [
"$$user",
{
userInteractions: {
$filter: {
input: "$$user.userInteractions",
cond: {
$ne: [
"$$this.userId",
{
$toObjectId: "633eb753c8e3d3fd71d1c254"
}
]
}
}
}
}
]
}
}
}
}
}
])
Demo # Mongo Playground

Return only matched documents with regexFind

I have an aggregate query which correctly "marks" the matched documents but returns all the documents on the collection. How do I return only the matched documents?
Here's my query:
db.trainers.aggregate([
{ $addFields: { returnObject: { $regexFind: { input: "$username", regex: /master/ } } } },
]);
// 1
{
"_id": ObjectId("5fe1c555607a0d05492dc481"),
"email": "PraXXXes0#gmail.com",
"username": "816XXX063",
"created": ISODate("2020-12-22T10:07:17.172Z"),
"returnObject": null,
}
// 2
{
"_id": ObjectId("5fe046caddfee639193a4880"),
"email": "HobbiXXXXious#gmail.com ",
"username": "PoXXXXmaster75785",
"created": ISODate("2020-12-21T06:55:06.262Z"),
"returnObject": {
"match": "master",
"idx": NumberInt("4"),
"captures": [ ]
},
}
I do not want those returnObject nulls...
Thanks

using $elemMatch in projection with field choosing

I'm trying to select only some fields in document while also using $elemmatch. It turned out the field selection is getting ignored.
Given a document like this:
{
"author": "Robin Sharma",
"data": [
{
"translation": "en",
"content": "foo",
"unwanted_content": "huyu1",
},
{
"translation": "id",
"content": "bar",
"unwanted_content": "huyu2",
{
],
}
I'm using find() with this projection config:
const projection = {
author: 1,
data: {
$elemMatch: {
translation: "en"
},
},
}
Expected
{
"author": "Robin Sharma",
"data": [
{
"translation": "en",
"content": "foo"
},
],
}
Actual
{
"author": "Robin Sharma",
"data": [
{
"translation": "en",
"content": "foo",
"unwanted_content": "huyu1",
},
],
}
I'm still not sure how to get rid of the "unwanted_content" field.
You can achieve your required result using aggregate as:
db.collection.aggregate([
{
$unwind: "$data"
},
{
$match: {
"data.translation": "en"
}
},
{
$group: {
_id: "$author",
data: {
$push: {
translation: "$data.translation",
content: "$data.content"
}
}
}
}
])
I think you can do something like this to get only selected fields from subdocument.
db.collection.find({"data.translation": "en"},{author: 1, "data.content": 1, "data.translation": 1})

Add conditional and in array of object, mongodb

I have a document like this
{
"_id": {
"$oid": "5c7369826023661073802f63"
},
"participants": [
{
"id": "ABC",
"nickname": "USER1",
},
{
"id": "DEF",
"nickname": "USER2",
}
]},... etc, et
I want to find the record that has the two ids that you provide
I try with this.
moodel.aggregate([
{
$match:{'participants.id':idOne}
},{
$project:{
list:{
$filter:{
input:'$list',
as:'item',
cond: {$eq: ['$$item.participants.id', idTwo]}
}
},
}
}
])
but the result is:
[ { _id: 5c7369826023661073802f63, list: null }]
I want it to return only the record that match the two ids.
use $elematch and $in
https://docs.mongodb.com/manual/reference/operator/query/elemMatch/
https://docs.mongodb.com/manual/reference/operator/query/in/
db.moodel.find({"participants": {$elemMatch: {id: {$in: [idOne, idTwo]}}}})

$elementMatch query in mongodb

I need to find elements which have product.typeCode in ["800", "200", "400"]
{
"_id": "stdcl13#ml.com",
"_class": "com.mongodb.BasicDBObject",
"accounts": [{
"number": "96398-00910620286__DISABILITY",
"product": {
"typeCode": "400",
"nameCode": "401"
},
"dependents": [],
"_id": "stdcl13#ml.com96398-00910620286__DISABILITYDSB"
}, {
"number": "96398-00910620286__LIFECNV",
"product": {
"typeCode": "300",
"nameCode": "LIFECNV"
},
"dependents": [],
"_id": "stdcl13#ss.com"
}]
}
I wrote this query, but its not returning the results
find( {
accounts: {
$elemMatch: {
product: {
typeCode: {
$in: ["400"]
}
}
}
}
})
Please try the below query. You can add the additional values in the IN clause (800, 200, 400).
db.collection.find({ "accounts.product.typeCode" : {
$in: ["400"]
}
}
);
With all three values:-
db.productlist.find({ "accounts.product.typeCode" : {
$in: ["400", "800", "200"]
}
}
);