猫鼬 - 如何分组和填充?

时间:2014-08-10 17:05:33

标签: javascript node.js mongodb mongoose aggregation-framework

我使用MongoDB和Mongoose作为我的ODM,并且我尝试在同一语句中使用populategroup by进行查询。

这是我的简单文档模型:

var userSchema = new Schema({
    username: String
});

var messageSchema = new Schema({
    from: { type: Schema.ObjectId, ref: 'User' },
    to: { type: Schema.ObjectId, ref: 'User' },
    message: String,
    date: { type: Date, default: Date.now }
});

我只是试图为每个用户收集每条消息,并与他谈话的每个用户进行分组。我试过这样:

this.find({ 'to': user })
    .sort({ 'date': 1 })
    .group('from')
    .populate(['from', 'to'])
    .exec(callback);

但是,不幸的是,我的模型没有group方法。你有什么解决办法吗?

谢谢。

3 个答案:

答案 0 :(得分:18)

使用$ lookup populate的示例,lookup填充为数组,因此$ unwind。

Option Explicit
Sub insertCheckboxes()

  Dim myBox As CheckBox
  Dim myCell As Range

  Dim cellRange As String
  Dim cboxLabel As String
  Dim linkedColumn As String

  cellRange = InputBox(Prompt:="Cell Range", _
    Title:="Cell Range")

  linkedColumn = InputBox(Prompt:="Linked Column", _
    Title:="Linked Column")

  cboxLabel = InputBox(Prompt:="Checkbox Label", _
    Title:="Checkbox Label")

  With ActiveSheet
    For Each myCell In .Range(cellRange).Cells
      With myCell
        Set myBox = .Parent.CheckBoxes.Add(Top:=.Top, _
          Width:=.Width, Left:=.Left, Height:=.Height)

        With myBox
          .LinkedCell = linkedColumn & myCell.Row
          .Caption = cboxLabel
          .Name = "checkbox_" & myCell.Address(0, 0)
        End With

        .NumberFormat = ";;;"
      End With

    Next myCell
  End With
End Sub

答案 1 :(得分:11)

这里使用的更好选项是.aggregate(),这是一个本机代码实现,与使用JavaScript引擎处理结果的MongoDB的.group()方法不同。

虽然不直接支持像.populate()这样的方法,但这是设计的,因为聚合管道和其他方法不会严格返回基于当前模型架构的响应。由于“假设”是你正在做的事情是错误的,它只是一个原始对象响应。

然而,没有什么可以阻止您将响应“转换”为mongoose文档,然后使用所需路径调用.populate()的模型形式:

Message.aggregate(
    [
        { "$match": { "to": user } },
        { "$sort": { "date": 1 } },
        { "$group": { 
            "_id": "from",
            "to": { "$first": "$to" },
            "message": { "$first": "$message" },
            "date": { "$first": "$date" },
            "origId": { "$first": "$_id" }
        }}
    ],
    function(err,results) {
        if (err) throw err;
        results = result.map(function(doc) { 
            doc.from = doc._id
            doc._id = doc.origId;
            delete doc.origId;
            return new Message( doc ) 
        });
        User.populate( results, { "path": "from to" }, function(err,results) {
            if (err) throw err;
            console.log( JSON.stringify( results, undefined, 4 ) );
        });
    }
)

当然,这只是真正从运营商隐含的每个“来自”返回$first消息。

或许你所谓的“分组”实际意味着“排序”:

Message.find({ "to": user })
    .sort({ "from": 1, "date": 1 })
    .populate("from to")
    .exec(function(err,messsages) {
        if (err) throw err;
        console.log( JSON.stringify( messages, undefined, 4 ) );
    });

由于您的上下文显示“所有消息”,而不是分组运算符暗示的内容,例如.aggregate().group()集合方法。因此,消息通过排序“组合在一起”,而不是任何特定的分组。

后者听起来就像你真正想要的那样,但如果你真的打算真正“分组”,那么就会有聚合示例以及如何使用.populate()

答案 2 :(得分:0)

这是我按单元类型对单元进行分组的方式

分组之前

[
{
    "_id": "5f68d604d47d3517ac3f00a1",
    "active": true,
    "unitName": "3",
    "unitType": [
        {
            "_id": "5f5b0a20c546f803d36f43b2",
            "active": true,
            "facilities": [
                "5f5b0977c546f803d36f43b0",
                "5f5b096ac546f803d36f43ae"
            ],
            "typeName": "Deluxe Room",
            "numberOfBeds": 2,
            "rate": 15000,
            "__v": 0
        }
    ],
    "status": "CLEANING",
    "createdAt": "2020-09-21T16:34:12.189Z",
    "__v": 0
},
{
    "_id": "5f6adb612bf2c33614d9d28e",
    "active": true,
    "unitName": "1",
    "unitType": [
        {
            "_id": "5f5b0a20c546f803d36f43b2",
            "active": true,
            "facilities": [
                "5f5b0977c546f803d36f43b0",
                "5f5b096ac546f803d36f43ae"
            ],
            "typeName": "Deluxe Room",
            "numberOfBeds": 2,
            "rate": 15000,
            "__v": 0
        }
    ],
    "status": "READY",
    "createdAt": "2020-09-23T05:21:37.746Z",
    "__v": 0
}]

汇总

Unit.aggregate([
    {
        $match:{
            _id : {
                $nin : reservedUnits
            }
        }
    },
    {
        $lookup: {
            from: 'unittypes',
            localField: 'unitType',
            foreignField: '_id',
            as: 'unitType'
        }
    },
    {
        $project: {
            unitType: {
                createdAt: 0
            }
        }
    },
    {$group : {_id : "$unitType", units: { $push: "$$ROOT" }}},
    {
        $project: {
            _id : {
                facilities: 0
            },
            units: {
                unitType: 0
            }
        }
    },
]);

结果

[
{
    "_id": [
        {
            "_id": "5f5b0a20c546f803d36f43b2",
            "active": true,
            "typeName": "Deluxe Room",
            "numberOfBeds": 2,
            "rate": 15000,
            "__v": 0
        }
    ],
    "units": [
        {
            "_id": "5f68d604d47d3517ac3f00a1",
            "active": true,
            "unitName": "3",
            "status": "CLEANING",
            "createdAt": "2020-09-21T16:34:12.189Z",
            "__v": 0
        },
        {
            "_id": "5f6adb612bf2c33614d9d28e",
            "active": true,
            "unitName": "1",
            "status": "READY",
            "createdAt": "2020-09-23T05:21:37.746Z",
            "__v": 0
        }
    ]
}]