programing

Mongoose - 그룹화 및 채우기 방법

subpage 2023. 7. 3. 22:55
반응형

Mongoose - 그룹화 및 채우기 방법

MongoDB와 Mongoose를 ODM으로 사용하고 있으며 다음을 사용하여 쿼리를 작성하려고 합니다.populate그리고.group 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방법.이 일을 해결할 해결책이 있습니까?

감사해요.

예를 들어 $lookup populate를 사용하면 lookup이 배열로 채워지므로 $unwind가 됩니다.

Message.aggregate(
    [
        { "$match": { "to": user } },
        { "$sort": { "date": 1 } },
        { "$group": { 
            "_id": "from",
            "to": { "$first": "$to" },
            "message": { "$first": "$message" },
            "date": { "$first": "$date" },
            "origId": { "$first": "$_id" }
        }},
        { "$lookup": {
             "from": "users",
             "localField": "from",
             "foreignField": "_id",
             "as": "from"
        }},
        { "$lookup": {
             "from": "users",
             "localField": "to",
             "foreignField": "_id",
             "as": "to"
        }},
        { "$unwind": { "path" : "$from" } },
        { "$unwind": { "path" : "$to" } }
    ],
    function(err,results) {
        if (err) throw err;
        return results;
    }
)

여기서 사용하기에 더 좋은 옵션은 입니다. 이것은 자바스크립트 엔진을 사용하여 결과를 처리하는 MongoDB의 방법과는 달리 네이티브 코드 구현입니다.

같은 방법.populate()그러나 직접 지원되지 않으며, 집계 파이프라인 및 기타 메서드가 현재 모델의 스키마를 기반으로 하는 응답을 엄격하게 반환하지 않기 때문에 이는 설계에 의한 것입니다.그것이 당신이 하고 있는 일이라고 "가정"하는 것은 잘못된 것이기 때문에, 그것은 단지 원시 객체 응답일 뿐입니다.

그러나 응답을 mongoose 문서로 "캐스팅"한 다음 필요한 경로로 의 모델 양식을 호출하는 것을 막을 수 있는 것은 없습니다.

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 ) );
        });
    }
)

물론, 그것은 운영자가 암시하는 것처럼 각 "발신자"의 메시지를 정말로 반환합니다.

"그룹화 기준"이 실제로 의미하는 것은 "정렬"입니다.

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()그것으로

유닛 유형별로 유닛을 그룹화한 방법입니다.

그룹화 전

[
{
    "_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
        }
    ]
}]

언급URL : https://stackoverflow.com/questions/25231022/mongoose-how-to-group-by-and-populate

반응형