2009-12-05 6 views
7

중첩 된 세트 (예 : 주석 트리)를 MongoDB에 저장하는 가장 좋은 방법은 무엇입니까?MongoDB 중첩 세트

모든 댓글에는 부모 댓글과 아동 댓글 (답변)이있을 수 있습니다.

이처럼 저장 : 우리는, 예를 들어,지도없이 "베드로 주석 모든 포스트"를 요청 할 수 없기 때문에

{ 
    title: "Hello", 
    body: "Please comment me!", 
    comments: [ 
     { 
      author: "Peter", 
      text: "Hi there", 
      answers: [ 
        { 
         author: "Peter", 
         text: "Hi there", 
         answers: [ 
           { author: "Ivan", text: "Hi there" }, 
           { author: "Nicholas", text: "Hi there" } 
         ] 
        }, 
        { author: "Ivan", text: "Hi there" }, 
        { author: "Nicholas", text: "Hi there" }, 
      ] 
     }, 
     { author: "Ivan", text: "Hi there" }, 
     { author: "Nicholas", text: "Hi there" }, 
    ] 
} 

는 멋진하지 않습니다/줄일 수 있습니다.

답변

3

완벽한 솔루션이 없다고 생각합니다. 앱에서 어떤 작업이 더 중요한지에 따라 달라집니다. 저는 Silicon Alley Insider가 MongoDB에 중첩 된 주석을 저장한다고 생각합니다. 그건 당신이 더 열심히 언급 쿼리를하지 않습니다.

하나의 옵션은 배열의 모든 주석 작성자 목록을 게시하는 최상위 레벨에 저장하는 것입니다. 이것을 비정규 화 된 데이터라고 생각하십시오. 그러면 특정 댓글 작성자와 관련된 모든 게시물을 쉽게 찾을 수 있습니다. 그런 다음 드릴 다운하려면 map/reduce 또는 db.eval()을 사용하여 내포 된 게시물 정보를 가져옵니다.

다른 하나의 메모 - 단일 문서를 다루는 경우 db.eval()은 map/reduce보다 가볍습니다. $ 또한 옵션이 있지만 느릴 수 있으므로 위에서 언급 한 추가 '의견 작성자 목록'이 마음에 들었습니다. 배열을 쉽게 색인 할 수있는 것은 아닙니다 (문서의 'Multikey'참조).

은 참조 : DM의 포스트 드와이트 리먼에서 링크에서 http://groups.google.com/group/mongodb-user/browse_thread/thread/df8250573c91f75a/e880d9c57e343b52?lnk=gst&q=trees#e880d9c57e343b52

2

가 배열 될이 작업을 수행하기 위해 경로 키를 사용한다고 언급하고 또 다른 방법은 정규식을

{ 
    path : "a.b.c.d.e.f" 
} 

과 일치하고

{ 
    path : ["a", "b", "c", "d", "e", "f"] 
} 

db.test.ensureIndex({path: 1}) 

꽤 빨리 만들어야합니다. 각 노드는 하나의 경로에있을 수있는 경우

다음 "는"

의 모든 아이를 찾을 것이 목록

db.test.find({path: "a"}) 

에서의 위치에 대한 걱정을 할 필요가 없습니다 것입니다 경로 이름 대신 아마 노드의 _id를 사용할 것입니다. 조심해야 할

업데이트

  • 한 가지 인덱스가 만에 하나 개의 배열을 가질 수 있다는 것입니다.
  • 쿼리에 설명문을 사용하십시오.

    db.test.발견 ({경로 : {$ 지역 : [ "A", "B"]})

당신에게

db.test.find({path: {$in: ["a", "b"]}}).explain() 
{ 
     "cursor" : "BtreeCursor path_1 multi", 
     "nscanned" : 2, 
     "nscannedObjects" : 2, 
     "n" : 1, 
     "millis" : 0, 
     "nYields" : 0, 
     "nChunkSkips" : 0, 
     "isMultiKey" : true, 
     "indexOnly" : false, 
     "indexBounds" : { 
       "path" : [ 
         [ 
           "a", 
           "a" 
         ], 
         [ 
           "b", 
           "b" 
         ] 
       ] 
     } 
} 

하지만

db.test.find({path: {$all: ["a", "b"]}}).explain() 
{ 
     "cursor" : "BtreeCursor path_1", 
     "nscanned" : 1, 
     "nscannedObjects" : 1, 
     "n" : 1, 
     "millis" : 0, 
     "nYields" : 0, 
     "nChunkSkips" : 0, 
     "isMultiKey" : true, 
     "indexOnly" : false, 
     "indexBounds" : { 
       "path" : [ 
         [ 
           "a", 
           "a" 
         ] 
       ] 
     } 
} 

은 첫 번째 요소를 사용하고 있습니다 b에 대한 모든 일치하는 결과를 스캔합니다.
a가 루트 요소이거나 대부분의 레코드에있는 경우 효율적인 인덱스 쿼리 대신 거의 모든 레코드 스캔을 수행합니다.

관련 문제