Find existing object into an array in nodejs - javascript

Hi this is my collection i just want to look userId into subcriber array if both userId exist into the subcriber array than not create new collection return same channelId. If both userId not exist into subcriber array then create new document how can i search userids in an array.
this is my collection.
{
"_id" : ObjectId("58dd1013e973fc0004743443"),
"createdAt" : ISODate("2017-03-30T14:02:59.175Z"),
"updatedAt" : ISODate("2017-03-30T14:02:59.175Z"),
"timestamp" : "2017-03-30",
"channelId" : "CH-EU7D",
"createdById" : "58dcc3cd9a7a301308b62857",
"message" : "",
"subcriber" : [
{
"userId" : "58dcc3cd9a7a301308b62857",
"channelId" : "CH-EU7D",
"_id" : ObjectId("58dd1013e973fc0004743444"),
"status" : "accepted"
},
{
"userId" : "58dcc3ec9a7a301308b62859",
"channelId" : "CH-EU7D",
"_id" : ObjectId("58dd1013e973fc0004743445"),
"status" : "pending"
}
],
"__v" : 0
}
I have tried this but not working.
Channel.find({ 'subcriber.userId': b.userId }, { $and: [{ 'subcriber.userId': b.friendId }] }

In nodejs you can use JavaScript Array.prototype.some() method with your json array to test if there's any matching useId, you will need to write something like:
function checkUserId(array, userId) {
return array.some(function(element) {
return userId === element.userId;
});
}
This is a Demo snippet:
function checkUserId(array, userId) {
return array.some(function(element) {
return userId === element.userId;
});
}
var json = {
"_id": "58dd1013e973fc0004743443",
"createdAt": "2017-03-30T14:02:59.175Z",
"updatedAt": "2017-03-30T14:02:59.175Z",
"timestamp": "2017-03-30",
"channelId": "CH-EU7D",
"createdById": "58dcc3cd9a7a301308b62857",
"message": "",
"subcriber": [{
"userId": "58dcc3cd9a7a301308b62857",
"channelId": "CH-EU7D",
"_id": "58dd1013e973fc0004743444",
"status": "accepted"
},
{
"userId": "58dcc3ec9a7a301308b62859",
"channelId": "CH-EU7D",
"_id": "58dd1013e973fc0004743445",
"status": "pending"
}
]
};
//Check an existing userId
console.log(checkUserId(json.subcriber, "58dcc3ec9a7a301308b62859"));
//Check a non existing userId
console.log(checkUserId(json.subcriber, "58dcc3ec9a7a3000000000859"));

for this type of problem can use $elemMatch of mongodb.
db.getCollection('channels').find({subcriber:{"$elemMatch":{userId:"58dcc3cd9a7a301308b62857",userId:'58dcc3ec9a7a301308b62859'}}})

Related

How can i optimize below query in Mongoose?

Basically, I want to fetch data from collection where pincode field(inside Location array) is matched by req.body
I'm getting my desired output but I'm not sure if it's a optimized way or not (look in Mongoose query part)
Here's my Json:
{
"_id" : ObjectId("6115b2cc1681596a10072f97"),
"vendorStatus" : "Active",
"name" : "harshit singh bhutani",
"email" : "sharsh2106#gmail.com",
"vId" : 12121,
"contact" : 121212,
"cities" : "dell",
"isMidnight" : "NA",
"location" : [
{
"delivery" : 1266,
"dc" : "High",
"midnight" : "Active",
"isLive" : "NA",
"_id" : ObjectId("612433c27292d11154bc4d4d"),
"pincode" : 123100,
"city" : "dek"
},
{
"delivery" : 23,
"dc" : "High",
"midnight" : "Active",
"isLive" : "NA",
"_id" : ObjectId("612441473cb5766a2457d6db"),
"pincode" : 1212,
"city" : "dd"
}
],
"createdAt" : ISODate("2021-08-12T23:46:20.407Z"),
"updatedAt" : ISODate("2021-09-03T10:51:34.756Z"),
"__v" : 73
}
Here's my query in Mongoose:
const { pin } = req.body;
const vendor = await Vendor.find({ vendorStatus: "Active" });
const pincode = vendor.map((item) => {
return item.location.find((i) => {
if (i.pincode === Number(pin) && i.isLive === "Active") {
return i;
}
});
});
const pincodefound = pincode.filter(Boolean);
if (pincodefound.length === 0) {
res.status(404);
throw Error("Product is not Deliverable at this Pincode");
} else {
return res.json({
pincodefound,
});
}
First I use map to iterate then I used find to grab the matched pincode after that I'm getting array with output and null value so I use filter to get only pincode
though I get my desired output BUT still I'm not sure weather its a optimized approach or not.
If I understood correctly your JS code you want to get only the value into the location array which match the condition.
In this case is a better way to do everything in a query. You can use an aggregation pipeline.
This query:
First match by vendorStatus: "Active like your find query.
Then use $unwind to deconstruct the array and look in each value.
$match to find a value which pincode and isLive are desired values.
And last stage is $project to show only values you want, in this case, the location values.
const pincode = await Vendor.aggregate([
{
"$match": {
"vendorStatus": "Active"
}
},
{
"$unwind": "$location"
},
{
"$match": {
"location.pincode": pin,
"location.isLive": "Active"
}
},
{
"$project": {
"delivery": "$location.delivery",
"dc": "$location.dc",
"midnight": "$location.midnight",
"isLive": "$location.isLive",
"_id": "$location._id",
"pincode": "$location.pincode",
"city": "$location.city"
}
}
]);
Example here

Can i filter one collection that has _id in other collection and have result on in mongodb

I have the collection "A" like this
{
"_id" : ObjectId("5c4c1f2a5173562961468b30"),
"name" : "first"
},
{
"_id" : ObjectId("57c162f267045ec439ba2485"),
"name" : "second"
}
Like above i have multiple doc in a collection,
Now i have colection "B" like below which has _id of Collections a's doc
{
"_id" : ObjectId("57d14ad36495a197593ab7ab"),
"a_id" : ObjectId("5c4c1f2a5173562961468b30"),
"name" : "ab"
},
{
"_id" : ObjectId("57d941503dd051cc04205e1e"),
"a_id" : ObjectId("5c4c1f2a5173562961468b30"),
"name" : "cd "
}
Now i need a query that will give me result collection "A" based on how many documents are associated with "B"
If "A" has 2 documents in "B" I need those 2 "B" documents
This simple aggregation make your result
db.A.aggregate([
{
"$lookup": {
"from": "B",
"localField": "_id",
"foreignField": "a_id",
"as": "docuentInB"
}
},
{
$match: {
$expr: { $gte: [{ $size: "$docuentInB" }, 2 ] }
}
},
{
$project: {
docuentInB: 0
}
}
])

how to find x number of documents where one property matches but other are distinct

Ok, imagine a collection like this:
[
{
"_id" : ObjectId("5b5f76eb2bfe4a1e9c473bd2"),
"machine" : "NY-D800",
"level" : "Fatal",
},
{
"_id" : ObjectId("5b5f76eb2bfe4a1e9c473bd2"),
"machine" : "NY-D889",
"level" : "Fatal",
},
{
"_id" : ObjectId("5b5f76eb2bfe4a1e9c473bd2"),
"machine" : "NY-D889",
"level" : "Info",
},
{
"_id" : ObjectId("5b5f76eb2bfe4a1e9c473bd2"),
"machine" : "NY-D800",
"level" : "Fatal",
},
...
]
I want to find documents that have level set to 'Fatal' but I don't want to return duplicates (duplicate machine). So for example 'NY-D800' is listed twice with 'Fatal' so I would want it to be returned only once. Finally I would like to limit the values returned to 10 items.
Recapping:
level = 'Fatal'
only unique values determined by machine
limit to 10 docs
Is this possible with MongoDB, Mongoose?
I tried this:
Logs
.distinct({'level': 'Fatal'})
.limit(10)
.exec(function (err, response){
var result = {
status: 201,
message: response
};
if (err){
result.status = 500;
result.message = err;
} else if (!response){
result.status = 404;
result.message = err;
}
res.status(result.status).json(result.message);
});
You can first $match with the level "Fatal" and then apply $group with machine
Logs.aggregate([
{ "$match": { "level": "Fatal" }},
{ "$group": {
"_id": "$machine",
"level": { "$first": "$level" },
}},
{ "$limit": 10 },
{ "$project": { "machine": "$_id", "level": 1, "_id": 0 }}
])

Mongodb update operation inside sub array

I am extremely new to mongodb and am facing a little trouble with an update operation. Here is the document:
{
"username" : "amitverma",
"notifications" : {
"notification_add_friend" : [
{
"sender" : "macbook",
"action" : "",
"type" : "",
"objectType" : "request",
"objectUrl" : "",
"isUnread" : true
},
{
"sender" : "safari",
"action" : "",
"type" : "",
"objectType" : "request",
"objectUrl" : "",
"isUnread" : true
},
{
"sender" : "chrome",
"action" : "",
"type" : "",
"objectType" : "request",
"objectUrl" : "",
"isUnread" : true
}
]
},
"_id" : ObjectId("526598c86f45240000000001")
}
{
"username" : "macbook",
"notifications" : {
"notification_add_friend" : [
{
"sender" : "amitverma",
"action" : "",
"type" : "",
"objectType" : "a_r",
"objectUrl" : "",
"isUnread" : true
}
]
},
"_id" : ObjectId("526598d06f45240000000002")
}
I want to remove the sub array with {"sender":"safari"} within "username":"amitverma"
I have tried $elemMatch with $set, but just couldn't get the query correctly.
You don't want to use $set here, but $pull (see docs), and while you could use $elemMatch to further specify your query, you do not need to.
The following would pull all add friend notifications with {"sender": "safari"} from the sub array of documents matching {"username": "amitverma"}
db.yourcollection.update({"username": "amitverma"}, {
$pull: {"notifications.notifications_add_friend": {"sender": "safari"}}
})
As to your comment, if you wanted to update a particular element you would use $set in combination with $elemMatch and the positional operator $. For your example, something like:
db.yourcollection.update({
"username": "amitverma",
"notifications.notifications_add_friend": {
$elemMatch: {"sender": "safari"}
}
}, {
$set: {
"notifications.notifications_add_friend.$.isUnread": false
}
})

How do I query referenced objects in MongoDB?

I've got two collections in my Mongo database, and the Foos contain references to one or more Bars:
Foo: {
prop1: true,
prop2: true,
bars: [
{
"$ref": "Bar",
"$id": ObjectId("blahblahblah")
}
]
}
Bar: {
testprop: true
}
What I want is to find all of the Foos that have at least one Bar that has its testprop set to true. I've tried this command, but it doesn't return any results:
db.Foo.find({ "bars.testprop" : { "$in": [ true ] } })
Any ideas?
You can now do it in Mongo 3.2 using $lookup
$lookup takes four arguments
from: Specifies the collection in the same database to perform the join with. The from collection cannot be sharded.
localField: Specifies the field from the documents input to the $lookup stage. $lookup performs an equality match on the localField to the foreignField from the documents of the from collection.
foreignField: Specifies the field from the documents in the from collection.
as: Specifies the name of the new array field to add to the input documents. The new array field contains the matching documents from the from collection.
db.Foo.aggregate(
{$unwind: "$bars"},
{$lookup: {
from:"bar",
localField: "bars",
foreignField: "_id",
as: "bar"
}},
{$match: {
"bar.testprop": true
}}
)
You can't. See http://www.mongodb.org/display/DOCS/Database+References
You have to do it in the client.
We have had a similar issue as we use MongoDB (3.4.4, actually 3.5.5 for testing) in combination with Morphia where we use #Referenece on a couple of entities. We are though not that happy with this solution and are considering removing these declarations and instead do the reference lookups manually.
I.e. we have a company collection and a user collection. The user entity in Morphia contains a #Refrence declaration on a company entity. The respective company collections contains entries like:
/* 1 */
{
"_id" : ObjectId("59a92501df01110fbb6a5dee"),
"name" : "Test",
"gln" : "1234567890123",
"uuid" : "f1f86961-e8d5-40bb-9d3f-fdbcf549066e",
"creationDate" : ISODate("2017-09-01T09:14:41.551Z"),
"lastChange" : ISODate("2017-09-01T09:14:41.551Z"),
"version" : NumberLong(1),
"disabled" : false
}
/* 2 */
{
"_id" : ObjectId("59a92501df01110fbb6a5def"),
"name" : "Sample",
"gln" : "3210987654321",
"uuid" : "fee69ee4-b29c-483b-b40d-e702b50b0451",
"creationDate" : ISODate("2017-09-01T09:14:41.562Z"),
"lastChange" : ISODate("2017-09-01T09:14:41.562Z"),
"version" : NumberLong(1),
"disabled" : false
}
while the user collections contains the following entries:
/* 1 */
{
"_id" : ObjectId("59a92501df01110fbb6a5df0"),
"userId" : "admin",
"userKeyEncrypted" : {
"salt" : "78e0528db239fd86",
"encryptedAttribute" : "e4543ddac7cca9757721379e4e70567bb13956694f473b73f7723ac2e2fc5245"
},
"passwordHash" : "$2a$10$STRNORu9rcbq4qYUMld4G.HJk8QQQQBmAswSNC/4PBn2bih0BvjM6",
"roles" : [
"ADMIN"
],
"company" : {
"$ref" : "company",
"$id" : ObjectId("59a92501df01110fbb6a5dee")
},
"uuid" : "b8aafdcf-d5c4-4040-a96d-8ab1a8608af8",
"creationDate" : ISODate("2017-09-01T09:14:41.673Z"),
"lastChange" : ISODate("2017-09-01T09:14:41.765Z"),
"version" : NumberLong(1),
"disabled" : false
}
/* 2 */
{
"_id" : ObjectId("59a92501df01110fbb6a5df1"),
"userId" : "sample",
"userKeyEncrypted" : {
"salt" : "e3ac48695dea5f51",
"encryptedAttribute" : "e804758b0fd13c219c3fc383eaa9267b70f7b8a1ed74f05575add713ce11804a"
},
"passwordHash" : "$2a$10$Gt2dq1vy4J9MeqDnXjokAOtvFcvbhe/g9wAENXFPaPxLAw1L4EULG",
"roles" : [
"USER"
],
"company" : {
"$ref" : "company",
"$id" : ObjectId("59a92501df01110fbb6a5def")
},
"uuid" : "55b62d4c-e5ee-408d-80c0-b79e02085b02",
"creationDate" : ISODate("2017-09-01T09:14:41.873Z"),
"lastChange" : ISODate("2017-09-01T09:14:41.878Z"),
"version" : NumberLong(1),
"disabled" : false
}
/* 3 */
{
"_id" : ObjectId("59a92501df01110fbb6a5df2"),
"userId" : "user",
"userKeyEncrypted" : {
"salt" : "ab9df671340a7d8b",
"encryptedAttribute" : "7d8ad4ca6ad88686d810c70498407032f1df830596f72d931880483874d9cce3"
},
"passwordHash" : "$2a$10$0FLFw3ixW79JIBrD82Ly6ebOwnEDliS.e7GmrNkFp2nkWDA9OE/RC",
"uuid" : "d02aef94-fc3c-4539-a22e-e43b8cd78aaf",
"creationDate" : ISODate("2017-09-01T09:14:41.991Z"),
"lastChange" : ISODate("2017-09-01T09:14:41.995Z"),
"version" : NumberLong(1),
"disabled" : false
}
In order to create a special company user view we also wanted to dereference the company in the user and only include selected fields. Based on a comment within a bug report we learned that MongoDB provides a $objectToArray: "$$ROOT.element" operation which basically splits fields of the given elements into key and value pairs. Note that $objectToArray operation was added in MongoDB version 3.4.4!
An aggregation on the company element contained in the user collection using the $objectToArray operation may look like below:
dp.user.aggregate([{
$project: {
"userId": 1,
"userKeyEncrypted": 1,
"uuid":1,
"roles": 1,
"passwordHash": 1,
"disabled": 1,
company: { $objectToArray: "$$ROOT.company" }
}
}])
The result of above aggregation looks like this:
/* 1 */
{
"_id" : ObjectId("59a92501df01110fbb6a5df0"),
"userId" : "admin",
"userKeyEncrypted" : {
"salt" : "78e0528db239fd86",
"encryptedAttribute" : "e4543ddac7cca9757721379e4e70567bb13956694f473b73f7723ac2e2fc5245"
},
"passwordHash" : "$2a$10$STRNORu9rcbq4qYUMld4G.HJk8QQQQBmAswSNC/4PBn2bih0BvjM6",
"roles" : [
"ADMIN"
],
"uuid" : "b8aafdcf-d5c4-4040-a96d-8ab1a8608af8",
"disabled" : false,
"company" : [
{
"k" : "$ref",
"v" : "company"
},
{
"k" : "$id",
"v" : ObjectId("59a92501df01110fbb6a5dee")
}
]
}
/* 2 */
{
"_id" : ObjectId("59a92501df01110fbb6a5df1"),
"userId" : "sample",
"userKeyEncrypted" : {
"salt" : "e3ac48695dea5f51",
"encryptedAttribute" : "e804758b0fd13c219c3fc383eaa9267b70f7b8a1ed74f05575add713ce11804a"
},
"passwordHash" : "$2a$10$Gt2dq1vy4J9MeqDnXjokAOtvFcvbhe/g9wAENXFPaPxLAw1L4EULG",
"roles" : [
"USER"
],
"uuid" : "55b62d4c-e5ee-408d-80c0-b79e02085b02",
"disabled" : false,
"company" : [
{
"k" : "$ref",
"v" : "company"
},
{
"k" : "$id",
"v" : ObjectId("59a92501df01110fbb6a5def")
}
]
}
/* 3 */
{
"_id" : ObjectId("59a92501df01110fbb6a5df2"),
"userId" : "user",
"userKeyEncrypted" : {
"salt" : "ab9df671340a7d8b",
"encryptedAttribute" : "7d8ad4ca6ad88686d810c70498407032f1df830596f72d931880483874d9cce3"
},
"passwordHash" : "$2a$10$0FLFw3ixW79JIBrD82Ly6ebOwnEDliS.e7GmrNkFp2nkWDA9OE/RC",
"uuid" : "d02aef94-fc3c-4539-a22e-e43b8cd78aaf",
"disabled" : false,
"company" : null
}
Now it's simply a matter of filtering unwanted stuff (i.e. users that have no company assigned and selecting the right array entries) in order to feed the $lookup operation #sidgate has already explained and copy the value of the dereferenced company into the user response.
I.e. an aggregation like the one below will perform an join and add the data of the company to users that have a company assigned as the as value defined in the lookup:
db.user.aggregate([
{ $project: { "userId": 1, "userKeyEncrypted": 1, "uuid":1, "roles": 1, "passwordHash": 1, "disabled": 1, company: { $objectToArray: "$$ROOT.company" }} },
{ $unwind: "$company" },
{ $match: { "company.k": "$id"} },
{ $lookup: { from: "company", localField: "company.v", foreignField: "_id", as: "company_data" } }
])
The result to the above aggregation can be seen below:
/* 1 */
{
"_id" : ObjectId("59a92501df01110fbb6a5df0"),
"userId" : "admin",
"userKeyEncrypted" : {
"salt" : "78e0528db239fd86",
"encryptedAttribute" : "e4543ddac7cca9757721379e4e70567bb13956694f473b73f7723ac2e2fc5245"
},
"passwordHash" : "$2a$10$STRNORu9rcbq4qYUMld4G.HJk8QQQQBmAswSNC/4PBn2bih0BvjM6",
"roles" : [
"ADMIN"
],
"uuid" : "b8aafdcf-d5c4-4040-a96d-8ab1a8608af8",
"disabled" : false,
"company" : {
"k" : "$id",
"v" : ObjectId("59a92501df01110fbb6a5dee")
},
"company_data" : [
{
"_id" : ObjectId("59a92501df01110fbb6a5dee"),
"name" : "Test",
"gln" : "1234567890123",
"uuid" : "f1f86961-e8d5-40bb-9d3f-fdbcf549066e",
"creationDate" : ISODate("2017-09-01T09:14:41.551Z"),
"lastChange" : ISODate("2017-09-01T09:14:41.551Z"),
"version" : NumberLong(1),
"disabled" : false
}
]
}
/* 2 */
{
"_id" : ObjectId("59a92501df01110fbb6a5df1"),
"userId" : "sample",
"userKeyEncrypted" : {
"salt" : "e3ac48695dea5f51",
"encryptedAttribute" : "e804758b0fd13c219c3fc383eaa9267b70f7b8a1ed74f05575add713ce11804a"
},
"passwordHash" : "$2a$10$Gt2dq1vy4J9MeqDnXjokAOtvFcvbhe/g9wAENXFPaPxLAw1L4EULG",
"roles" : [
"USER"
],
"uuid" : "55b62d4c-e5ee-408d-80c0-b79e02085b02",
"disabled" : false,
"company" : {
"k" : "$id",
"v" : ObjectId("59a92501df01110fbb6a5def")
},
"company_data" : [
{
"_id" : ObjectId("59a92501df01110fbb6a5def"),
"name" : "Sample",
"gln" : "3210987654321",
"uuid" : "fee69ee4-b29c-483b-b40d-e702b50b0451",
"creationDate" : ISODate("2017-09-01T09:14:41.562Z"),
"lastChange" : ISODate("2017-09-01T09:14:41.562Z"),
"version" : NumberLong(1),
"disabled" : false
}
]
}
As can hopefully be seen we only have the two users that contained a company reference and the two users now have also the complete company data in the response. Now additional filtering can be applied to get rid of the key/value helper and also to hide unwanted data.
The final query we came up with looks like this:
db.user.aggregate([
{ $project: { "userId": 1, "userKeyEncrypted": 1, "uuid":1, "roles": 1, "passwordHash": 1, "disabled": 1, company: { $objectToArray: "$$ROOT.company" }} },
{ $unwind: "$company" },
{ $match: { "company.k": "$id"} },
{ $lookup: { from: "company", localField: "company.v", foreignField: "_id", as: "company_data" } },
{ $project: { "userId": 1, "userKeyEncrypted": 1, "uuid":1, "roles": 1, "passwordHash": 1, "disabled": 1, "companyUuid": { $arrayElemAt: [ "$company_data.uuid", 0 ] } } }
])
Which finally returns our desired representation:
/* 1 */
{
"_id" : ObjectId("59a92501df01110fbb6a5df0"),
"userId" : "admin",
"userKeyEncrypted" : {
"salt" : "78e0528db239fd86",
"encryptedAttribute" : "e4543ddac7cca9757721379e4e70567bb13956694f473b73f7723ac2e2fc5245"
},
"passwordHash" : "$2a$10$STRNORu9rcbq4qYUMld4G.HJk8QQQQBmAswSNC/4PBn2bih0BvjM6",
"roles" : [
"ADMIN"
],
"uuid" : "b8aafdcf-d5c4-4040-a96d-8ab1a8608af8",
"disabled" : false,
"companyUuid" : "f1f86961-e8d5-40bb-9d3f-fdbcf549066e"
}
/* 2 */
{
"_id" : ObjectId("59a92501df01110fbb6a5df1"),
"userId" : "sample",
"userKeyEncrypted" : {
"salt" : "e3ac48695dea5f51",
"encryptedAttribute" : "e804758b0fd13c219c3fc383eaa9267b70f7b8a1ed74f05575add713ce11804a"
},
"passwordHash" : "$2a$10$Gt2dq1vy4J9MeqDnXjokAOtvFcvbhe/g9wAENXFPaPxLAw1L4EULG",
"roles" : [
"USER"
],
"uuid" : "55b62d4c-e5ee-408d-80c0-b79e02085b02",
"disabled" : false,
"companyUuid" : "fee69ee4-b29c-483b-b40d-e702b50b0451"
}
Some final note to this approach: This aggregation isn't very fast, sadly, but at least it gets the job done. I haven't tested it with an array of references as originally asked though this may require some additional unwindings probably.
Update: A further way of aggregating the data, which is more in line with the comments in the above mentioned bug report, can be seen below:
db.user.aggregate([
{ $project: { "userId": 1, "userKeyEncrypted": 1, "uuid":1, "roles": 1, "passwordHash": 1, "disabled": 1, companyRefs: { $let: { vars: { refParts: { $objectToArray: "$$ROOT.company" }}, in: "$$refParts.v" } } } },
{ $match: { "companyRefs": { $exists: true } } },
{ $project: { "userId": 1, "userKeyEncrypted": 1, "uuid":1, "roles": 1, "passwordHash": 1, "disabled": 1, "companyRef": { $arrayElemAt: [ "$companyRefs", 1 ] } } },
{ $lookup: { from: "company", localField: "companyRef", foreignField: "_id", as: "company_data" } },
{ $project: { "userId": 1, "userKeyEncrypted": 1, "uuid":1, "roles": 1, "passwordHash": 1, "disabled": 1, "companyUuid": { $arrayElemAt: [ "$company_data.uuid", 0 ] } } }
])
Here the $let: { vars: ..., in: ... } operation copies the key and value of the reference into an own object and thus allows later on to lookup the reference via the corresponding operation.
Which of these aggregations performs better has yet to be profiled.
Well.. you could query the Bar Model for the _id of all documents with testprop: true, then do a find $in and populate bars on the Foo Model with an array of those _id's you got from the first query.. :P
Maybe that counts as "In the Client" :P just a thought.
It wasn't possible before, but improvements from Mongo v3.4 we can get very close to it.
You can do it with mongo-join-query. Your code would look like this:
const mongoose = require("mongoose");
const joinQuery = require("mongo-join-query");
joinQuery(
mongoose.models.Foo,
{
find: { "bars.testprop": { $in: [true] } },
populate: ["bars"]
},
(err, res) => (err ? console.log("Error:", err) : console.log("Success:", res.results))
);
How does it work?
Behind the scenes mongo-join-query will use your Mongoose schema to determine which models to join and will create an aggregation pipeline that will perform the join and the query.
Disclosure: I wrote this library to tackle precisely this use case.

Categories

Resources