2016-06-07 2 views
2

"_id"로 정의 된 문서에서 하위 문서의 배열에서 최신 항목을 가져와야합니다.

문서는 다음과 같습니다

이 쿼리와
{ 
"_id": "nex67", 
"ownedparts": [ 
    { 
     "id": "tool1", 
     "history": [ 
      { 
       "time": ISODate("2016-06-07T09:12:54.015Z"), 
       "value": 300 
      }, 
      { 
       "time": ISODate("2016-06-07T09:12:54.015Z"), 
       "value": 240 
      } 
     ] 
    }, 
    { 
     "id": "screw1", 
     "history": [ 
      { 
       "time": ISODate("2016-06-07T09:12:54.015Z"), 
       "value": 500 
      } 
     ] 
    } 
]} 

내가 "도구 1"의 전체 역사를 얻을 :

db.users.find( 
{ 
    "_id": "nex67", 
    "ownedparts.id": "tool1" 
}, { "ownedparts.history.$": 1 }) 

그리고 난 최신 항목을받을 수 있나요 명령으로

하지만 반환 "tool1"과 "screw1"둘 다에서 :

db.users.find( 
{"_id": "nex67"}, 
{"ownedparts.history": { $slice: -1 }}) 

그래서 기본적으로 나는이 쿼리를 결합하는 데 도움이 필요합니다. nex67의 tool1에서 최신 기록 항목을 가져올 수 있습니다.

내가 다음과 같아야 필요 결과 :

{ 
    "_id" : "nex67", 
    "ownedparts" : [ 
      { 
        "id" : "tool1", 
        "history" : [ 
          { 
            "time" : ISODate("2016-06-07T09:12:54.015Z"), 
            "value" : 240 
          } 
        ] 
      } 
    ]} 

답변

2

이것은 $arrayElemAt$filter 연산자를 사용하여 MongoDB 3.2에 수행하는 최적의 방법. 생산

db.users.aggregate(
    [ 
     { "$match": { "_id": "nex67", "ownedparts.id": "tool1" } }, 
     { "$project": { 
      "ownedparts": { 
       "$let": { 
        "vars": { 
         "el": { 
          "$arrayElemAt": [ 
           { "$filter": { 
            "input": "$ownedparts", 
            "as": "own", 
            "cond": { "$eq": [ "$$own.id", "tool1" ] } 
           }}, 
           0 
          ] 
         } 
        }, 
        "in": { 
         "id": "$$el.id", 
         "history": { "$arrayElemAt": [ "$$el.history", -1 ] } 
        } 
       } 
      } 
     }} 
    ] 
) 

:

{ 
    "_id" : "nex67", 
    "ownedparts" : { 
     "id" : "tool1", 
     "history" : { 
      "time" : ISODate("2016-06-07T09:12:54.015Z"), 
      "value" : 240 
     } 
    } 
} 
+0

'$ arrayElemAt' 안에'$ filter'의 완벽한 조합! – profesor79

-1

시도를이

db.users.find( 
     {"_id": "nex67"}, 
     {"ownedparts.$.history": { $slice: -1 }}) 

에 그리고 당신은이 문제가 simbol와 $으로 사이

db.users.find( 
{ 
     "_id": "nex67", 
     "ownedparts.id": "tool1" 
}, { "ownedparts.history.$": 1 }) 

상담이 소유 한 부품 및 기록을 사용하여 배열을 가져옵니다.

db.users.find( 
{ 
     "_id": "nex67", 
     "ownedparts.id": "tool1" 
}, { "ownedparts.$.history": 1 }) 
+1

이 모든 하위 배열 요소를 반환 – profesor79

1

우리가 중첩 된 배열을 가지고 있기 때문에 그것은 사소한 문제가 아닙니다. 집계 프레임 워크를 사용하여 첫 번째 레코드 project을 선택하고 중첩을 줄이기 위해 unwind 배열을, 마지막으로 project2을 사용하여 필요에 따라 문서를 재구성해야합니다. match은 처리중인 문서의 양을 다시 줄이기위한 필터로 사용됩니다.

var match = { 
    $match : { 
     "_id" : "nex67" 
    } 
} 

var project = { 
    $project : { 
     _id : 1, 
     ownedpartsFirst : { 
      $slice : ["$ownedparts", 1] 
     } 
    } 
} 
var unwind = { 
    $unwind : "$ownedpartsFirst" 
} 
var project2 = { 
    $project : { 
     _id : 1, 
     ownedparts : 
     [{ 
       id : "$ownedpartsFirst.id", 
       history : { 
        $slice : ["$ownedpartsFirst.history", -1] 
       } 
      } 
     ] 
    } 
} 

db.collectionName.aggregate([match, project, unwind, project2]) 

출력 :

{ 
    "_id" : "nex67", 
    "ownedparts" : [ 
     { 
      "id" : "tool1", 
      "history" : [ 
       { 
        "time" : ISODate("2016-06-07T09:12:54.015Z"), 
        "value" : 240.0 
       } 
      ] 
     } 
    ] 
} 
+0

이 너무 작동하지만, 내가 더 최적의 것 때문에 응답으로 $ arrayElemAt를 사용하는 하나를 선택하고있다. – damnputer

관련 문제