Reputation: 3511
I would like to filter nested properties after lookup in mongodb. I cannot find proper example in documentation. I use aggregation and in the last stage I have to pass few conditions. I want to filter by properties tightened in lookup stage.
This is my query:
db.collection('leagues').aggregate([
{
$match: {
_id: ObjectID(leagueId)
}
},
{
$lookup: {
from: "league_configs",
localField: "_id",
foreignField: "leagueId",
as: "configs"
}
},
{
$lookup: {
from: "events",
localField: "_id",
foreignField: "leagueId",
as: "events"
}
},
{
$match: {
$and: [{
"events": {
"isCalculated": {
$eq: false
},
"isDeleted": {
$eq: false
},
"startDate": {
$lte: new Date()
}
},
}]
}
}
])
Example league object:
{
"_id" : ObjectId("57c6bf5934db7e18b8af650c"),
"name" : "League1",
"adminId" : ObjectId("57c5a08b8857ad1da099e8de"),
"isStarted" : false,
"isFinished" : false,
"users" : [
ObjectId("57c5a08b8857ad1da099e8de")
],
"isPublic" : true,
"createdDate" : "2016-08-31T13:28:25+02:00",
"updatedDate" : ISODate("2016-08-31T12:28:09.064Z"),
"currentStage" : 1,
"isDeleted" : false
}
Example event object:
{
"_id" : ObjectId("57c6bfca34db7e18b8af650f"),
"home" : "home",
"guest" : "guest",
"description" : null,
"result" : "X",
"resultHome" : 1,
"resultGuest" : 1,
"startDate" : ISODate("2016-08-31T18:30:00.000Z"),
"type" : "1",
"specialPoints" : null,
"leagueStage" : 1,
"isDeleted" : false,
"isCalculated" : false,
"leagueId" : ObjectId("57c6bf5934db7e18b8af650c"),
"updatedDate" : ISODate("2016-09-02T06:52:45.544Z")
}
Any advices?
Upvotes: 1
Views: 2893
Reputation: 39226
Here is the query. You can use "$elemMatch" to filter the data from "events" collection. Also, I have renamed the lookup result as "events_docs" rather than "event" for clarity.
Please note that I have removed the first lookup on "league_configs" as I don't have that collection data. You can add that back and try the full query.
The below query work fine with the data you have provided.
Query:-
db.leagues.aggregate([
{
$match: {
_id: ObjectId("57c6bf5934db7e18b8af650c")
}
},
{
$lookup: {
from: "events",
localField: "_id",
foreignField: "leagueId",
as: "events_docs"
}
},
{
$match: { "events_docs": {$elemMatch: {"isDeleted" : false,"isCalculated" : false, "startDate": {
$lte: new Date()
}} } }
}
]);
Output:-
{
"_id" : ObjectId("57c6bf5934db7e18b8af650c"),
"name" : "League1",
"adminId" : ObjectId("57c5a08b8857ad1da099e8de"),
"isStarted" : false,
"isFinished" : false,
"users" : [
ObjectId("57c5a08b8857ad1da099e8de")
],
"isPublic" : true,
"createdDate" : "2016-08-31T13:28:25+02:00",
"updatedDate" : ISODate("2016-08-31T12:28:09.064Z"),
"currentStage" : 1,
"isDeleted" : false,
"events_docs" : [
{
"_id" : ObjectId("57c6bfca34db7e18b8af650f"),
"home" : "home",
"guest" : "guest",
"description" : null,
"result" : "X",
"resultHome" : 1,
"resultGuest" : 1,
"startDate" : ISODate("2016-08-31T18:30:00.000Z"),
"type" : "1",
"specialPoints" : null,
"leagueStage" : 1,
"isDeleted" : false,
"isCalculated" : false,
"leagueId" : ObjectId("57c6bf5934db7e18b8af650c"),
"updatedDate" : ISODate("2016-09-02T06:52:45.544Z")
}
]
}
Test Case 2:- I ran the same query for league id = ObjectId("57ce74076eae72aafab03013"). The query fetched zero documents.
League Document:-
{
"_id" : ObjectId("57ce74076eae72aafab03013"),
"name" : "League1",
"adminId" : ObjectId("57c5a08b8857ad1da099e8de"),
"isStarted" : false,
"isFinished" : false,
"users" : [
ObjectId("57c5a08b8857ad1da099e8de")
],
"isPublic" : true,
"createdDate" : "2016-08-31T13:28:25+02:00",
"updatedDate" : ISODate("2016-08-31T12:28:09.064Z"),
"currentStage" : 1,
"isDeleted" : false
}
Events Documents:-
This event doesn't have any league id.
{
"_id" : ObjectId("57ce74256eae72aafab03014"),
"home" : "home",
"guest" : "guest",
"description" : null,
"result" : "X",
"resultHome" : 1,
"resultGuest" : 1,
"startDate" : ISODate("2016-08-31T18:30:00.000Z"),
"type" : "1",
"specialPoints" : null,
"leagueStage" : 1,
"isDeleted" : false,
"isCalculated" : false,
"updatedDate" : ISODate("2016-09-02T06:52:45.544Z")
}
This event has league id (ObjectId("57ce74076eae72aafab03013")), however the isDeleted and isCalculated attributes are set to true. So, the query didn't fetch this document.
{
"_id" : ObjectId("57ce74ea6eae72aafab03015"),
"home" : "home",
"guest" : "guest",
"description" : null,
"result" : "X",
"resultHome" : 1,
"resultGuest" : 1,
"startDate" : ISODate("2016-08-31T18:30:00.000Z"),
"type" : "1",
"specialPoints" : null,
"leagueStage" : 1,
"isDeleted" : true,
"isCalculated" : true,
"leagueId" : ObjectId("57ce74076eae72aafab03013"),
"updatedDate" : ISODate("2016-09-02T06:52:45.544Z")
}
Upvotes: 2