2016-09-24 2 views
1

저는 MongoDB를 처음 접했고 새로운 프로젝트를 위해 특정 쿼리를 설정하는 데 어려움을 겪어 왔습니다.MongoDB의 배열에서 중첩 된 객체를 찾는 방법은 무엇입니까?

난이 (단순화 된 버전)과 같은 데이터 구조를 가지고

games: {_id: ..., scenes: [{_id: ..., views: [{_id: ...}]}]} 

(즉 게임 장면들의 집합을 포함, 장면보기의 컬렉션을 포함).

여기에서 쿼리하려는 것은 특정 뷰 객체입니다. 대답은 $ elemMatch를 사용하는 것이지만, 어떻게 설정해야합니까? 연구의 조금 장난 + 후, 나는 장면 얻기 위해이 작업을 수행 할 수 있습니다 알고

db.collection("games").findOne({ 
    _id: ObjectId(req.params.gid)}, 
    { 
    scenes: { 
     $elemMatch: {_id: ObjectId(req.params.sid)} 
    } 
}... 

을하지만 그것은 단지 (_id에 의해) 내가 관심이있는 특정보기를 가져옵니다 있도록 어떻게 내가이 확장 할 ?

나는 언제나 수동으로 for 루프를 사용하여 찾고있는 뷰 객체를 찾을 수 있다고 생각한다. 이것은 또 다른 질문을 제기한다. Wrt 성능은 Mongo를 사용하여 이와 같은 쿼리를 수행하는 것이 더 좋으며 컬렉션 전체를 반복하기 위해 전체 문서를 가져 와서 수동으로 수행하는 것이 좋습니다.

+0

배열 내에서 개체 만 가져올 수 없습니다. 전체 문서를 가져와야합니다. 독자적으로 하위 문서를 원할 경우 집계 프레임 워크를 사용해야합니다. – cdbajorin

+0

@cdbajorin "독자적으로"라고 말하면 내가 원하지 않는 _id 값을 가진 뷰를 필터링하는 것이 불가능하다는 것을 의미합니까? 아니면 당신이 찾고있는 쿼리가'result.scenes [0] .views [0]'과 같은 구조체를 제공한다는 것을 의미합니까? 나는 후자와 괜찮아. – JSideris

답변

1

컬렉션이 크지 않고이 작업이 비교적 드문 경우 집계 프레임 워크로 수행하는 것이 좋습니다. 그러나이 작업이 빈번하고 성능이 중요하다면 응용 프로그램 수준의 쿼리를 사용하는 것이 좋습니다. 이 컬렉션 인 경우 그래서

:

> db.col.find().pretty() 
{ 
    "_id" : ObjectId("57e6a5404897ec06f1c3d86f"), 
    "games" : [ 
     { 
      "_id" : "game1", 
      "scenes" : [ 
       { 
        "_id" : "scene1", 
        "views" : [ 
         { 
          "_id" : "view1" 
         } 
        ] 
       } 
      ] 
     } 
    ] 
} 
{ 
    "_id" : ObjectId("57e6a5d24897ec06f1c3d870"), 
    "games" : [ 
     { 
      "_id" : "game1", 
      "scenes" : [ 
       { 
        "_id" : "scene11", 
        "views" : [ 
         { 
          "_id" : "view111" 
         }, 
         { 
          "_id" : "view112" 
         }, 
         { 
          "_id" : "view113" 
         } 
        ] 
       }, 
       { 
        "_id" : "scene12", 
        "views" : [ 
         { 
          "_id" : "view121" 
         } 
        ] 
       } 
      ] 
     }, 
     { 
      "_id" : "game2", 
      "scenes" : [ 
       { 
        "_id" : "scene21", 
        "views" : [ 
         { 
          "_id" : "view211" 
         } 
        ] 
       } 
      ] 
     } 
    ] 
} 

와의 당신이 ID "view112", 당신이 할 수와보기를 찾으려면 가정 해 봅시다 어떤 경우에, 이것은 당신이 집계하고 $unwind 함께 할 거라고 어떻게

db.col.aggregate([ 
    { $unwind: "$games"}, 
    { $unwind: "$games.scenes"}, 
    { $unwind: "$games.scenes.views"}, 
    { 
     $match: { 
      "games.scenes.views._id": "view112" 
     } 
    } 
]) 

당신은 얻을 것이다 : 할

{ 
    "_id": ObjectId("57e6a5d24897ec06f1c3d870"), 
    "games": { 
     "_id": "game1", 
     "scenes": { 
      "_id": "scene11", 
      "views": { 
       "_id": "view112" 
      } 
     } 
    } 
} 
+0

이것은 멋집니다. 이 특정보기 ID가 다른 장면에 존재하지 않아야합니까? 이 쿼리에 대한 인덱스를 만드는 방법에 대한 팁은 무엇입니까? – JSideris

+0

이 뷰 ID가 응답에 여러 요소를 가져 오는 것보다 다른 위치에 표시되는 경우 즉, 특정 게임, 뷰, 씬 등에 집중하기 위해 '$ match' 지시어에 조건을 추가 할 수 있습니다. 다른 질문에 대해서는 원래 컬렉션이 아니지만 모든 'unwind'결과로 인덱스가 생성되지 않기 때문에 인덱스가 도움이되지 않습니다. –

+0

뷰 ID를 알고 있으므로 처음에는 집계 상단에 '$ match'가 있어야 해당보기가있는 게임 만 필터링 할 수 있습니다. – cdbajorin

0

나는 그것을 얻지 않는다, 요 u로 직접 문의 할 수 있습니다

db.collection("games").findOne({"scenes.views._id":ObjectId(req.params.vid)},{_id:0,"scenes.$.views":1}); 

다른 장면을 장면에서 제거해야합니다 (말장난 의도). 하지만 그래도 $는 한 번만 사용할 수 있기 때문에 여전히 여러보기를 제공합니다. 루프가 중요하다고 생각합니다.

집계에 대해 제안 하겠지만 비용이 많이 듭니다. 에 대한 쿼리를 달성하거나 문서 및 루프를 통해 그것을 달성했다. 확실히 쿼리를 통해 달성하기 위해 갈 것이고 적은 데이터를 가져올수록 성능이 향상됩니다.

+0

scene.views.id와 req.params.vid를 비교할 의향이 있습니까 (sid와 반대입니다, 장면에 사용중인 매개 변수)? _id : 0은 무엇을합니까? 뷰 ID는 ObjectId 객체이기도합니다. – JSideris

+0

그래, 그 req.params.vid, 나쁜, 대답을 업데이 트해야합니다. 그것이 객체 ID라면, 그것은 유일하다는 것이 보장됩니다. –

+0

두 번째 부분에 대해 _id : 0은 결과에 _id가 필요 없다고 말하고 있습니다. 그것은 투영 전략입니다. 1과 0으로 원하는 것을 설정할 수 있고 원하지 않는 것을 설정할 수 있습니다. –

관련 문제