MongoDB - $accumulator官网Demo转成真正的JS代码 - 方便理解

x33g5p2x  于2022-02-22 转载在 Go  
字(4.5k)|赞(0)|评价(0)|浏览(343)

官网的案例: https://docs.mongodb.com/manual/reference/operator/aggregation/accumulator/#mongodb-group-grp.-accumulator

数据

db.restaurants.insertMany([
  { "_id" : 1, "name" : "Food Fury", "city" : "Bettles", "cuisine" : "American" },
  { "_id" : 2, "name" : "Meal Macro", "city" : "Bettles", "cuisine" : "Chinese" },
  { "_id" : 3, "name" : "Big Crisp", "city" : "Bettles", "cuisine" : "Latin" },
  { "_id" : 4, "name" : "The Wrap", "city" : "Onida", "cuisine" : "American" },
  { "_id" : 5, "name" : "Spice Attack", "city" : "Onida", "cuisine" : "Latin" },
  { "_id" : 6, "name" : "Soup City", "city" : "Onida", "cuisine" : "Chinese" },
  { "_id" : 7, "name" : "Crave", "city" : "Pyote", "cuisine" : "American" },
  { "_id" : 8, "name" : "The Gala", "city" : "Pyote", "cuisine" : "Chinese" }
])

db.restaurants.aggregate([
{
  $group :
  {
    _id : { city: "$city" },
    restaurants:
    {
      $accumulator:
      {
        init: function(city, userProfileCity) {       
          return {
            max: city === userProfileCity ? 3 : 1,    
            restaurants: []                           
          }
        },
        initArgs: ["$city","Onida"],       
        accumulate: function(state, restaurantName) { 
          if (state.restaurants.length < state.max) {
            state.restaurants.push(restaurantName);
          }
          return state;
        },
        accumulateArgs: ["$name"],                    
        merge: function(state1, state2) {
          return {
            max: state1.max,
            restaurants: state1.restaurants.concat(state2.restaurants).slice(0, state1.max)
          }
        },
        finalize: function(state) {                   
          return state.restaurants
        },
        lang: "js"
      }
    }
  }
}
])

将上面的案例直接转换成真正的JS代码 == 更加的易懂

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body></body>
  <script>
    var objs = [
      { _id: 1, name: "Food Fury", city: "Bettles", cuisine: "American" },
      { _id: 2, name: "Meal Macro", city: "Bettles", cuisine: "Chinese" },
      { _id: 3, name: "Big Crisp", city: "Bettles", cuisine: "Latin" },
      { _id: 4, name: "The Wrap", city: "Onida", cuisine: "American" },
      { _id: 5, name: "Spice Attack", city: "Onida", cuisine: "Latin" },
      { _id: 6, name: "Soup City", city: "Onida", cuisine: "Chinese" },
      { _id: 7, name: "Crave", city: "Pyote", cuisine: "American" },
      { _id: 8, name: "The Gala", city: "Pyote", cuisine: "Chinese" },
    ];
    //分组 == 按city的值
    var groups = {};
    objs.forEach((item, index) => {
      if (!groups[item.city]) {
        groups[item.city] = [];
      }
      groups[item.city].push(item);
    });
    console.log("=============分组开始==============")
    console.log(groups);
    console.log("=============分组结束==============")
    //==========================MongoDB的聚合【直接粘贴复制的】==============================================
    function init(city, userProfileCity) {
      let state = {
        max: city === userProfileCity ? 3 : 1,
        restaurants: [],
      };
      return state;
    }
    function accumulate(state, restaurantName) {
      if (state.restaurants.length < state.max) {
        state.restaurants.push(restaurantName);
      }
      return state;
    }
    function merge(state1, state2) {
      return {
        max: state1.max,
        restaurants: state1.restaurants
          .concat(state2.restaurants)
          .slice(0, state1.max),
      };
    }
    function finalize(state) {                  
      return state.restaurants
    }  
    //========================================================================
    var initGroups = {};
    for( let groupName in  groups) {
      var groupElems = groups[groupName];
      initGroups[groupName] = JSON.parse(JSON.stringify(groupElems));
      var initGroupElems = initGroups[groupName];
      for(var index = 0 ; index < groupElems.length; index++) {
        //等价于 initArgs: ["$city","Onida"]
        let state = init(groupName, "Onida");
        //等价于accumulateArgs: ["$name"]
        initGroupElems[index] = accumulate(state, groupElems[index]["name"])
      }
      //等价于merge
      var metgeResult = initGroupElems.reduce( merge );
      //等价于finalize
      initGroups[groupName] = finalize(metgeResult);
    }
    console.log("=============分组聚合后的结果==开始============")
    console.log(initGroups);
    console.log("=============分组聚合后的结果==结束============")
   
  </script>
</html>

相关文章