sunmingtao / sample-code

3 stars 4 forks source link

m220 $lookup two way to implement #52

Closed sunmingtao closed 5 years ago

sunmingtao commented 5 years ago

Ticket https://university.mongodb.com/mercury/M220J/2019_October/chapter/Chapter_2_User-Facing_Backend/lesson/5bb67087b9a628479e54b95e/problem

My implementation (bad)

  public Document getMovie(String movieId) {
    if (!validIdValue(movieId)) {
      return null;
    }

    List<Bson> pipeline = new ArrayList<>();
    // match stage to find movie
    Bson match = Aggregates.match(Filters.eq("_id", new ObjectId(movieId)));
    pipeline.add(match);
    Bson lookup = Aggregates.lookup("comments",
            Arrays.asList(new Variable<String>("id123", "$_id")), 
            Arrays.asList(new Document("$match", new Document("$expr", new Document("$eq", Arrays.asList("$movie_id", "$$id123"))))), 
            "comments");
    pipeline.add(lookup);
    pipeline.add(unwind("$comments"));
    pipeline.add(sort(descending("comments.date")));
    pipeline.add(group("$_id", push("comments", "$comments"), first("fullplot", "$fullplot"), first("imdb", "$imdb"), first("year", "$year"), first("plot", "$plot"), first("genres", "$genres"), first("rated", "$rated"), first("metacritic", "$metacritic"), first("title", "$title"), first("language", "$language"), first("lastupdated", "$lastupdated"), first("writers", "$writers"), first("type", "$type"), first("tomatoes", "$tomatoes"), first("poster", "$poster"), first("num_mflix_comments", "$num_mflix_comments"), first("released", "$released"), first("awards", "$awards"), first("countries", "$countries"), first("cast", "$cast"), first("directors", "$directors"), first("runtime", "$runtime")));
    Document movie = moviesCollection.aggregate(pipeline).first();
    return movie;

  }
sunmingtao commented 5 years ago

Good implementation:

private Bson buildLookupStage(){
  List<Variable<String>> let = new ArrayList<>();
  let.add(new Variable<String>("id", "$_id"));

  // lookup pipeline
  Bson exprMatch = Document.parse("{'$expr': {'$eq': ['$movie_id', '$$id']}}");

  Bson lookupMatch = Aggregates.match(exprMatch);
  List<Bson> lookUpPipeline = new ArrayList<>();
  // lookup sort stage
  Bson sortLookup = Aggregates.sort(Sorts.descending("date"));

  lookUpPipeline.add(lookupMatch);
  lookUpPipeline.add(sortLookup);
  return Aggregates.lookup("comments", let, lookUpPipeline, "comments");
}

public Document getMovie(String movieId){

  if (!validIdValue(movieId)) {
   return null;
 }

 List<Bson> pipeline = new ArrayList<>();
 // match stage to find movie
 Bson match = Aggregates.match(Filters.eq("_id", new ObjectId(movieId)));
 pipeline.add(match);

 // comments lookup stage
 Bson lookup = buildLookupStage();
 if(lookup != null) {
   pipeline.add(lookup);
 }

 Document movie = moviesCollection.aggregate(pipeline)
         .batchSize(1)
         .iterator().tryNext();
 return movie;
}