2013-10-30 3 views
8

내부 데이터를 노출하는 nodejs REST 서비스와 함께 MongoDB를 사용하고 있습니다. $ ref를 사용하는 데이터를 조사하는 방법에 대한 질문이 있습니다. 여기

꽃밥 컬렉션에서 다른 객체 (세부 사항)에 대한 참조가 담고있는 객체의 샘플이다 Node.js를하고 MongoDB의 모듈을 사용하여 실제로

{ 
    "_id" : ObjectId("5962c7b53b6a02100a000085"), 
    "Title" : "test", 
    "detail" : { 
     "$ref" : "ObjDetail", 
     "$id" : ObjectId("5270c7b11f6a02100a000001") 
    }, 
    "foo" : bar 
} 

를, I는 다음을 수행

db.collection("Obj").findOne({"_id" : new ObjectID("5962c7b53b6a02100a000085"}, 
function(err, item) { 
    db.collection(item.$ref).findOne({"_id" : item.$id}, function(err,subItem){ 
     ... 
    }); 
}); 

사실 나는 2 개의 쿼리를 만들고 2 개의 개체를 얻습니다. 그것은

내 질문은 간단하다 "지연로드"(정확히하지만 거의)의 종류 : 그것은 가능한 한 쿼리에서 전체 객체 그래프를 검색하기 위해?

고맙습니다.

답변

4

아니요.

DBRef를 해결하려면 응용 프로그램이 참조 된 문서를 반환하기 위해 추가 쿼리를 수행해야합니다. 많은 드라이버에는 DBRef에 대한 쿼리를 자동으로 구성하는 도우미 메서드가 있습니다. 드라이버는 DBRef를 문서로 자동 해결하지 않습니다.

MongoDB docs http://docs.mongodb.org/manual/reference/database-references/에서.

+1

그리고 지금까지 사용되지 않고 있습니다 : 우리는 다음과 같은 방법을 제거했습니다 당신을위한 심판. – Brett

4

하나의 MongoDB 쿼리를 사용하여 $ ref와 함께 상위 개체를 가져올 수 있습니까?

아니, 그것은 불가능합니다. Mongo는 ref에 대한 내부 지원이 없으므로 응용 프로그램에 채우기 위해 응용 프로그램에 따라 다릅니다 (Brett's answer 참조).

하지만이 가능은 하나의 Node.js를 명령으로 모든 심판의와 부모 개체를 가져?

예, 그것은 가능합니다.Mongoose으로 할 수 있습니다. 그것은 build-in ref의 인구 지원을 가지고 있습니다. 작동 시키려면 데이터 모델을 약간 변경해야하지만, 찾고있는 것이 거의 있습니다. 물론 그렇게하기 위해 Mongoose는 당신이 한 두 개의 MongoDB 쿼리를 만들 것입니다.

1

아니, MongoDB를위한 거의 드라이버는 DBRef에 대한 특별 지원을 포함한다. 두 가지 이유가 있습니다.

  1. MongoDb에는 참조 된 문서를 검색 할 수있는 특별한 명령이 없습니다. 따라서 지원을 추가하는 드라이버는 인위적으로 결과 객체를 채 웁니다.
  2. API가 "베어 메탈 (bare metal)"일수록 의미가 적습니다. 사실, MongoDb 컬렉션은 스키마가 없으며, 참조가 깨지지 않고 문서를 저장하면 NodeJs 드라이버가 모든 참조가 실현 된 기본 문서를 가져온 경우 하위 문서가 포함됩니다. 물론, 그것은 엉망이 될 것입니다. 당신의 필드 값이 변화하지 않는 한

, 나는 DBRef 형 신경 쓰지 것이며, 대신 직접 ObjectId를 저장하는 것입니다.보시다시피, DBRef은 더 풍부한 객체가 유형 정보와 함께 저장되어야하므로 각 참조에 대해 많은 중복 디스크 공간이 필요하다는 점을 제외하면 실제로 이점을 제공하지 않습니다. 어느 쪽이든, 참조 된 콜렉션의 문서를 포함하는 문자열을 저장할 때 잠재적으로 불필요한 오버 헤드를 고려해야합니다.

많은 개발자와 MongoDb, Inc.는 기존 기본 드라이버 위에 개체 문서 매핑 계층을 추가했습니다. MongoDb 및 Nodejs에 대한 인기있는 옵션은 Mongoose입니다. MongoDb 서버는 참조 된 문서에 대한 실질적인 인식이 없으므로 참조의 책임은 클라이언트로 이동합니다. Mongoose는 특정 문서에서 특정 콜렉션을 일관되게 참조하는 것이 더 일반적이므로 참조를 스키마로 정의 할 수 있습니다. Mongoose는 스키마가 없습니다.

스키마 사용에 동의하고 스키마를 사용하는 것이 유용하다면 몽구스를 살펴볼 가치가 있습니다. 그것은 일련의 문서들로부터 (단일 모음집으로부터) 관련된 문서들을 효율적으로 가져올 수 있습니다. 항상 네이티브 드라이버를 사용하지만, 일반적으로 작업을 매우 효율적으로 수행하고보다 복잡한 응용 프로그램 아키텍처에서 힘든 일을 수행합니다.

populate 방법 (here)을 살펴보고 가능한지 확인해 보시기 바랍니다.

Demo  /* Demo would be a Mongoose Model that you've defined */ 
.findById(theObjectId) 
.populate('detail') 
.exec(function (err, doc) { 
    if (err) return handleError(err); 
    // do something with the single doc that was returned 
}) 

대신 항상 하나의 문서를 반환 findById의 경우, findpopulate에 사용 된 모든 문서 ' details 속성이 자동으로 채워집니다 돌아왔다. 똑같은 참조 문서를 여러 번 요청하는 것도 똑똑합니다.

Mongoose를 사용하지 않는 경우 가능한 경우 클라이언트 측 참조 조인을 수행하지 않으려면 $in 쿼리 연산자를 사용하여 최대한 많이 배치하는 것이 좋습니다.

+0

고맙습니다. 몽구스를 살펴 보겠습니다. –

1

나는 다음 예제와 원하는 결과에 도달 :이 솔루션은 최고 중 최고라고

collection.find({}, function (err, cursor) { 
    cursor.toArray(function (err, docs) { 
     var count = docs.length - 1; 
     for (i in docs) { 
      (function (docs, i) { 
       db.dereference(docs[i].ref, function(err, doc) { 
        docs[i].ref = doc; 
        if (i == count) { 
         (function (docs) { 
          console.log(docs); 
         })(docs); 
        } 
       }); 
      })(docs, i) 
     } 
    }); 
}); 

확실하지,하지만 그것은 내가 발견 간단한 솔루션입니다. db.dereference 방법은 MongoDB를 Nodejs API에서 삭제로 블라디미르

관련 문제