Kyle Buchanan
Kyle Buchanan

Reputation: 193

Get Document out of Array in mongoDB

I have a collection called season that looks like this:

[ 
  { 
    week: 1,
    matchups: [ 
        {
            home : ObjectId("1"),
            away : ObjectId("2")
        },
        {
            home : ObjectId("3"),
            away : ObjectId("4")
        },

    ],
    _id: 50fc50c9ce87149ee3000007 
  },
  { 
    week: 2,
    matchups: [ 
        {
            home : ObjectId("3"),
            away : ObjectId("1")
        },
        {
            home : ObjectId("2"),
            away : ObjectId("4")
        },
    ],
    _id: 50fc50c9ce87149ee3000008 
  }
]

I'm trying to get all of the matchups where the home OR away team is ObjectId("1"). I want the return to look like this:

[ 
  { 
    week: 1,
    matchups: [ 
        {
            home : ObjectId("1"),
            away : ObjectId("2")
        }

    ],
    _id: 50fc50c9ce87149ee3000007 
  },
  { 
    week: 2,
    matchups: [ 
        {
            home : ObjectId("3"),
            away : ObjectId("1")
        }
    ],
    _id: 50fc50c9ce87149ee3000008 
  }
]

Is it possible to get this result using on db.season.find()?

Upvotes: 0

Views: 98

Answers (2)

JohnnyHK
JohnnyHK

Reputation: 311865

As long as you have at most one potential matchups element to match, you can use the $elemMatch projection operator to do this:

db.seasons.find(
    {$or: [{'matchups.home': ObjectId("1")},{'matchups.away': ObjectId("1")}]}, 
    {week: 1, matchups: {
        $elemMatch: {$or: [{home: ObjectId("1")},{away: ObjectId("1")}]}
    }});

Same caveat as Wes regarding the invalidity of ObjectId("1").

Upvotes: 2

Eve Freeman
Eve Freeman

Reputation: 33155

Not with .find, but with .aggregate:

db.seasons.aggregate(
  {$match:{$or:[{"matchups.home":ObjectId("1")}, {"matchups.away":ObjectId("1")}]}}, 
  {$unwind:"$matchups"}, 
  {$match:{$or:[{"matchups.home":ObjectId("1")}, {"matchups.away":ObjectId("1")}]}}, 
  {$group:{_id:"$_id", week:{$first:"$week"}, matchups:{$addToSet:"$matchups"}}});
  1. first match filters on the ones that have your team (will make the rest more efficient if there are some records that don't contain your team)
  2. unwind breaks out the matchups
  3. second match filters on only the ones that have your team
  4. group rebuilds your records again

Limitations are the document size with aggregate. Hope this helps.

The best you can do with .find is the first match, and then filter the matchups on the application side, AFAIK.

Also, ObjectId("1") is invalid, FYI.

Upvotes: 1

Related Questions