【问题标题】:How to group records by a field in Mongoose?如何按 Mongoose 中的字段对记录进行分组?
【发布时间】:2015-11-16 21:14:54
【问题描述】:

我有一个 MongoDB 文档,其中的记录如下所示:

[
  { _id: id, category_name: 'category1', parent_category: null },
  { _id: id, category_name: 'category2', parent_category: null },
  { _id: id, category_name: 'subcategory1', parent_category: id_parent_1 },
  { _id: id, category_name: 'subcategory2', parent_category: id_parent_1 },
  { _id: id, category_name: 'subcategory3', parent_category: id_parent_2 },
  { _id: id, category_name: 'subcategory4', parent_category: id_parent_2 }
]

如您所见,我使用parent_categorynull 存储类别,子类别具有父类别的ID。我正在寻找的是将这些分组为某种格式,如下所示:

[
  { category_name: 'category1', categories: [
       { category_name: 'subcategory1', _id: id },
       { category_name: 'subcategory2', _id: id }
    ]
  },
  { category_name: 'category2', categories: [
       { category_name: 'subcategory3', _id: id },
       { category_name: 'subcategory4', _id: id }
    ]
  }
]

所以基本上将父类别与它们的子类别组成一个数组。我正在使用猫鼬。我尝试使用 MongoDB 提供的聚合框架,但无法获得所需的结果。 :(

我有权以任何可能需要的方式修改架构!

提前致谢!

【问题讨论】:

  • 您最初为什么要这样设计您的文档?也许你可以重新设计你的猫鼬模式并制作一些方法来验证 parent_id 以分配子类别
  • 只是两级分类吗?您的子类别可以有自己的子类别吗?
  • @JoseOsorio 我不太明白你的意思
  • @yarons 是的,只有两个级别,类别和子类别
  • 查看猫鼬的这个类别树库:github.com/incrediblesound/category-tree。这是作者的一篇博文:incrediblesound.github.io/blog/2014/07/27/…

标签: javascript node.js mongodb mongoose nosql


【解决方案1】:

您似乎将 Mongo 视为一个关系数据库(分离所有这些字段并通过查询将它们组合在一起)。你应该做的是重建你的模式。例如:

var CategorySchema = new Schema({
   category_name: String,
   subCategories:[subCategorySchema]
}

var subCategorySchema = new Schema({
   category_name: String
})

这样当你需要查询集合时很简单

db.find({category_name: "name of the category"}, function(){})

得到你需要的一切。

以防万一:您可以通过简单的更新将子类别添加到数组中。阅读this了解更多信息。

【讨论】:

  • 不得不稍微修改一下以满足我的需要,但总的来说这是我需要的。谢谢!
【解决方案2】:

如果您的架构未更改,请尝试此操作:

var MongoClient = require('mongodb').MongoClient

//connect away
MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {
  if (err) throw err;
  console.log("Connected to Database");

  //simple json record
    var document = [];
    //insert record
    //db.data.find({"parent_category":null }).forEach(function(data) {print("user: " + db.data.findOne({"parent_category":data._id })) })
    db.collection('data').find({"parent_category":null }, function(err, parentrecords) {
        if (err) throw err;
        var cat ={};
        parentrecords.forEach(function(data){
            cat["category_name"] = data["category_name"];
            db.collection('data').find({"parent_category":data._id },function(err, childrecords) {
                var doc = [];
                childrecords.forEach(function(childdata){
                    doc.push(childdata);
                        },function(){
                        cat["categories"] = doc;
                        document.push(cat);
                        console.log(document);
                    });
            });
        });
});
});

【讨论】:

    【解决方案3】:

    为了按字段对记录进行分组,请尝试在 Aggregation 中使用 $group。这对我有用。

    示例

    db.categories.aggregate(
       [
         { $group : { _id : {category_name:"$category_name"}, categories: { $push: {category_name:"$category_name",_id:"$_id"} } } }
       ]
    )
    

    参考MongoDB Aggregation

    希望这行得通。

    【讨论】:

      【解决方案4】:

      如果您想在不更改架构的情况下找出预期结果,那么您基本上遵循一些复杂的 mongo aggregation 查询。为了查找输出,我遵循以下步骤:

      1. 首先在$project 中检查parent_category 是否等于null 如果为真则添加_id 否则添加parent_category
      2. 现在文档结构看起来像新的key name as parent_id 呈现和parent_id 分组并推送剩余数据,如category_name and parent_category
      3. 之后使用 $setDifference$setIntersection 来区分父数据和子数据。
      4. 最后在unwind 中只有单个数组对象,因此这个单个数组对象和使用的项目仅显示要显示的那些字段。

      检查工作聚合查询如下:

      db.collectionName.aggregate({
          "$project": {
              "parent_id": {
                  "$cond": {
                      "if": {
                          "$eq": ["$parent_category", null]
                      },
                      "then": "$_id",
                      "else": "$parent_category"
                  }
              },
              "category_name": 1,
              "parent_category": 1
          }
      }, {
          "$group": {
              "_id": "$parent_id",
              "categories": {
                  "$push": {
                      "category_name": "$category_name",
                      "parent_category": "$parent_category"
                  }
              },
              "parentData": {
                  "$push": {
                      "$cond": {
                          "if": {
                              "$eq": ["$parent_category", null]
                          },
                          "then": {
                              "category_name": "$category_name",
                              "parent_category": "$parent_category"
                          },
                          "else": null
                      }
                  }
              }
          }
      }, {
          "$project": {
              "findParent": {
                  "$setIntersection": ["$categories", "$parentData"]
              },
              "categories": {
                  "$setDifference": ["$categories", "$parentData"]
              }
          }
      }, {
          "$unwind": "$findParent"
      }, {
          "$project": {
              "category_name": "$findParent.category_name",
              "categories": 1
          }
      }).pretty() 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-07-17
        • 1970-01-01
        • 1970-01-01
        • 2016-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多