programing

참조된 모델의 필드별 모델에 대한 Mongoose 중첩 쿼리

css3 2023. 6. 29. 20:20

참조된 모델의 필드별 모델에 대한 Mongoose 중첩 쿼리

스택 오버플로에 대한 이 주제에 대한 Q/A가 많은 것 같습니다만, 어디에서도 정확한 답을 찾을 수 없는 것 같습니다.

내가 가진 것:

회사 및 개인 모델이 있습니다.

var mongoose = require('mongoose');
var PersonSchema = new mongoose.Schema{
                        name: String, 
                        lastname: String};

// company has a reference to Person
var CompanySchema = new mongoose.Schema{
                        name: String, 
                        founder: {type:Schema.ObjectId, ref:Person}};

필요한 것:

"Robertson" 성을 가진 사람들이 설립한 모든 회사 찾기

제가 시도한 것:

Company.find({'founder.id': 'Robertson'}, function(err, companies){
    console.log(companies); // getting an empty array
});

그런 다음 사용자가 내장된 것이 아니라 참조된 것으로 판단되어 publit을 사용하여 founder-Person을 입력한 다음 find를 'Robertson' 성으로 사용하려고 했습니다.

// 1. retrieve all companies
// 2. populate their founders
// 3. find 'Robertson' lastname in populated Companies
Company.find({}).populate('founder')
       .find({'founder.lastname': 'Robertson'})
       .exec(function(err, companies) {
        console.log(companies); // getting an empty array again
    });

나는 여전히 사용자 ID가 문자열인 회사를 조회할 수 있습니다.하지만 제가 원하는 것은 정확히 아닙니다. 이해하시겠지만요.

Company.find({'founder': '525cf76f919dc8010f00000d'}, function(err, companies){
    console.log(companies); // this works
});

MongoDB는 조인을 지원하지 않기 때문에 단일 쿼리에서 이 작업을 수행할 수 없습니다.대신 몇 가지 단계로 나누어 설명해야 합니다.

// Get the _ids of people with the last name of Robertson.
Person.find({lastname: 'Robertson'}, {_id: 1}, function(err, docs) {

    // Map the docs into an array of just the _ids
    var ids = docs.map(function(doc) { return doc._id; });

    // Get the companies whose founders are in that set.
    Company.find({founder: {$in: ids}}, function(err, docs) {
        // docs contains your answer
    });
});

저는 이 질문에 꽤 늦었습니다 :p 하지만 저는 단지 비슷한 답을 찾고 있었고 같은 이유로 누군가 이것을 발견할 경우에 대비하여 제가 생각해낸 것을 공유하려고 생각했습니다.

mongoose 쿼리를 통해 이를 달성할 방법을 찾지 못했지만 MongoDB 집계 파이프라인을 사용하여 작동하는 것 같습니다.

찾고 있는 쿼리를 얻으려면 다음과 같은 작업을 수행할 수 있습니다.

const result=await Company.aggregate([
    {$lookup: {
        from: 'persons', 
        localField: 'founder', 
        foreignField: '_id', 
        as: 'founder'}
    },
    {$unwind: {path: '$founder'}},
    {$match: {'founder.lastname': 'Robertson'}}
]);

$lookup 처럼 행동함.populate()참조를 실제 데이터로 대체합니다.여러 문서를 일치시키는 데 사용할 수 있으므로 배열을 반환합니다.

$unwind 는 배열에서 항목을 제거하며, 이 경우 단일 요소 배열을 필드로 변환합니다.

$match 그런 다음 소리가 나며 쿼리와 일치하는 문서만 반환합니다.필요한 경우 엄격한 동일성보다 더 복잡한 일치를 수행할 수도 있습니다.

일반적으로 통합 파이프라인의 작동 방식은 사용자가 원하는 것을 얻을 때까지 각 단계에서 일치하는 문서를 지속적으로 수정하는 것입니다.

저는 이것에 대한 성능을 확인하지는 않았지만, 저는 확실히 불필요한 결과 서버 쪽을 걸러내는 것보다 Mongo가 작업을 하도록 하는 것을 선호합니다.

유일한 단점은 파이프라인이 일반적으로 문서의 모양을 바꾸기 때문에 결과가 몽구스 모델이 아닌 객체 배열에 불과하다는 것입니다.따라서 반환된 데이터에 모델의 방법을 사용할 수 없습니다.

Mongoose는 최근에 이 문제를 발견한 사람이 있을 경우 Publit(채우기)라는 기능을 통해 가입과 같은 기능을 지원합니다.

Mongoose 설명서에서 다음을 참조하십시오.

Story.findOne({ 
    title: 'Casino Royale' 
}).populate('author').exec(function (err, story) {
    if (err) return handleError(err);
    console.log('The author is %s', story.author.name);
    // prints "The author is Ian Fleming"
});

http://mongoosejs.com/docs/populate.html

언급URL : https://stackoverflow.com/questions/19380738/mongoose-nested-query-on-model-by-field-of-its-referenced-model