简体   繁体   中英

MongoDB nested document queries with conditions

I'm trying to wrap my head around some more complex MongoDB queries. I've read through a number of somewhat-related questions , but I haven't quite been able to figure out what would be the best approach for the situation I'm in. Say I'm trying to index a collection of DVD's with different club soccer matches recorded, and I've modeled the documents in the collection like the following (abbreviated):

{ 
  "dvdId" : "10021", 
  "dateSubmitted" : ISODate("2015-11-17T15:42:21.248Z"),
  "featuredPlayerNames": [
    "Sam B. Clement", 
    "John C. Carter", 
    "Gabriel M. Malinowski", 
    "Jimmy I. Vincent", 
    "George L. Spears", 
    "Roland M. Nelson", 
  ],
  "matches" : [ 
    { 
      "startTime" : 0,
      "winningTeamIndex": 0,
      "teams" : [ 
        { 
          "teamName": "Hornets",
          "players" : [ 
            { 
              "name" : "Sam B. Clement", 
              "position" : "striker" 
            }, 
            { 
              "name" : "John C. Carter", 
              "position" : "halfback" 
            },
          ] 
        }, 
        { 
          "teamName": "Hurricanes",
          "players" : [ 
            { 
              "name" : "Gabriel M. Malinowski", 
              "position" : "fullback" 
            }, 
            { 
              "name" : "Jimmy I. Vincent", 
              "position" : "keeper" 
            },
          ] 
        } 
      ] 
    },
    { 
      "startTime": 5602,
      "winningTeamIndex": 1,
      "teams" : [ 
        { 
          "teamName": "Raiders",
          "players" : [ 
            { 
              "name" : "Sam B. Clement", 
              "position" : "halfback" 
            }, 
            { 
              "name" : "George L. Spears", 
              "position" : "striker" 
            },
          ] 
        }, 
        { 
          "teamName": "Hurricanes",
          "players" : [ 
            { 
              "name" : "Roland M. Nelson", 
              "position" : "striker" 
            }, 
            { 
              "name" : "Jimmy I. Vincent", 
              "position" : "keeper" 
            },
          ] 
        } 
      ] 
    },    
  ], 
}

What I've done so far. I've figured out how to get it to do some simple operations on the first-level properties and arrays, such as returning DVD's featuring a player of interest and/or another player of interest; eg, db.dvds.find({featuredPlayerNames: {$in: ['Sam B. Clement', 'John C. Carter']}}); .

Where I need help. I'm now trying to figure out how I would query the Mongo database with more complex operations, such as return documents containing match(es) featuring the following conditions:

  • a team of interest is the winning team
  • a player of interest AND another player of interest on the same team
  • a player of interest AND another player of interest on different teams
  • a player of interest on the winning team
  • a player of interest playing a position of interest
  • a player of interest playing a position of interest AND a player of interest playing a position of interest on different teams

What would be the best approach to accomplish advanced queries such as these? After wandering in the documentation and from my reading of similar questions ( 1 2 3 4 5 6 7 8 9 10 11 12* 13* ), I've found I may need to use $elemMatch , $cond , $in , $all , $match , $unwind , $group , and/or the aggregation framework, but in addition to being unfamiliar with many of these, I also saw a lot of different opinions and approaches, and none that really seemed to combine nested queries with specific conditions (like a player on the winning team or players on different teams).

Now I could probably learn to do most of these given a push in the right direction. I'm also open to remodeling the structure of the data here if it seems something would work better for my case (provided I would be able to add more teams to a match as in 2v2v2).

Thank you!

In general it is faster and easier to structure your data in a manner that allows simple queries than to write complicated queries. Reformatting your data set might be a one-time cost, whereas a costly query might be executed millions of times.

Your questions:

  • teamX is a winning team
    • reformat the data to add matches.winningTeamName field
    • { matches.winningTeamName: teamX }
    • or reformat the data to add matches.teams.winner field
    • { matches.teams: { $elemMatch: { winner: true, teamName: teamX } } }
  • playerX and playerY on same team
    • matches.teams: { $and: [ {players.name: playerX}, {players.name, playerY} ] }
    • Or reformat the data to add matches.teams.playerList field
    • { matches.teams.playerList: { $all: [playerX, playerY] } }
  • playerX and playerY on different teams
    • not sure, I think you can do this with a combination of $and and $not but without having the db set up I'd be guessing.
  • playerX on winning team
    • reformat the data to add matches.teams.winner field
    • { matches.teams: { $elemMatch: { winner: true, players.name: playerX } } }
  • playerX playing positionX
    • { matches.teams.players: { $elemMatch: { name: playerX, position: positionX} } }
  • again with the different teams...

Hope that helps...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM