2014-07-24 2 views
0

시나리오 : MongoDB에있는 twitCount라는 컬렉션의 문서를 고려하십시오.mongoDB에 배열이있는 필드를 반환하고 해당 배열의 처음과 마지막 값을 반환하십시오.

{ 
"_id" : ObjectId("53d1340478441a1c0d25c40c"), 
"items" : [ 
    { 
     "date" : ISODate("2014-07-22T22:18:05.000Z"), 
     "value" : 4, 
     "_id" : ObjectId("53d134048b3956000063aa72") 
    }, 
    { 
     "date" : ISODate("2014-07-21T22:09:20.000Z"), 
     "value" : 10, 
     "_id" : ObjectId("53d134048b3956000063aa71") 
    } 
    ... 
], 
"ticker" : "OM:A1M" 

}

나는 첫 번째와 마지막 날짜 내부 "항목"를 가져 싶다. 나는 많은 "쿼리"를 시도했다. 그러나 나는 그것을 올바르게 할 수 없다. "시세 표시기"가 고유 한

다음 쿼리는 반환하는 유일한 것이지만 예상 한 모든 것을 반환합니다.

그래서 결국이 쿼리는 다음과 같은 결과를 반환합니다. [2013-02-01, 2014-07-24]; 정말 도움이 필요합니다. manual/core/aggregation의 모든 링크는 자주색이며 자세한 정보는 어디서 얻을 수 있는지 잘 모릅니다.

+0

나는 게으르다. 전체 배열을 투영 한 다음 그 결과에 대해 시프트와 팝을 수행한다.^ –

+0

몽고는 [$ 팝 연산자] (http : //docs.mongodb.org/manual/reference/operator/update/pop /) 예제 중 하나는 배열의 첫 번째 요소를 제거하는 것입니다. –

+0

또한 여기에 비슷한 문제를 해결하기 위해 slice를 사용하는 답변이 나와 있습니다. http://stackoverflow.com/questions/7223273/get-n-th-element-of-an-array-in-mongo –

답변

0

귀하의 의도가 귀하의 조건과 일치하는 단일 문서 또는 여러 문서로 작업하는 것이지 알기가 어렵습니다. 제안 된대로 단일 문서는 실제로 배열의 첫 번째 요소와 마지막 요소를 가져 오기 위해 단 하나의 결과에서 JavaScript 고유의 shiftpop 메서드를 사용하는 것입니다. 또한 $pop 같은 사업자가 영구적으로 업데이트에서 배열을 mondify로 다른 제안이 실제로 적용되지 않는 종류의 여기

twitCount.findOne({ "ticker": "OM:A1M" },function(err,doc) { 

    doc.items = doc.items.sort(function(a,b) { 
     return (a.date.valueOf() > b.date.valueOf()) ? 1 
      : (a.date.valueOf() < b.date.valueOf()) ? -1 : 0; 
    }); 
    doc.items = [doc.items.shift(),doc.items.pop()]; 

    console.log(doc); 
}) 

배열을 채택해야 할 수도 있습니다. 그리고 쿼리에 사용할 수있는 $slice 연산자는 배열 내용이 이미 정렬 된 경우에만 유용하게 사용할 수 있습니다. 추가적으로 처음과 마지막으로 반환하는 두 개의 쿼리를 만들려고합니다.

그러나 실제로 여러 문서에서이 작업을 수행하려는 경우 집계 프레임 워크가 답입니다. 배열로 작업 할 때 이해해야 할 중요한 부분은 배열에서 먼저파이프 라인 단계를 사용해야한다는 것입니다. 문서의 사본을 효과적으로 각 배열 요소에 대해 생성되는 형식이 "드 정상화"당신이 정말로 "항목을"원하는 경우 다시 배열로

twitCount.aggregate([ 
    // Match your "documents" first 
    { "$match": { "ticker": "OM:A1M" } }, 

    // Unwind the array 
    { "$unwind": "$items" }, 

    // Sort the values 
    { "$sort": { "items.date": 1 } }, 

    // Group with $first and $last items 
    { "$group": { 
     "_id": "$ticker", 
     "first": { "$first": "$items" }, 
     "last": { "$last": "$items" } 
    }} 
],function(err,result) { 

은 당신은 다르게 조금을 바로 할 수 있습니다 :

twitCount.aggregate([ 
    // Match your "documents" first 
    { "$match": { "ticker": "OM:A1M" } }, 

    // Unwind the array 
    { "$unwind": "$items" }, 

    // Sort the values 
    { "$sort": { "items.date": 1 } }, 

    // Group with $first and $last items 
    { "$group": { 
     "_id": "$ticker", 
     "first": { "$first": "$items" }, 
     "last": { "$last": "$items" }, 
     "type": { "$first": { "$const": [true,false] } } 
    }}, 

    // Unwind the "type" 
    { "$unwind": "$type" }, 

    // Conditionally push to the array 
    { "$group": { 
     "_id": "$_id", 
     "items": { 
      "$push": { 
       "$cond": [ 
        "$type", 
        "$first", 
        "$last" 
       ] 
      } 
     } 
    }} 
],function(err,result) { 

또는

당신의 $match 문은 단지 선택하도록하고 당신이 원하는 경우 다음 방금 초기 $group에 "$의 _id"의 ​​키를 변경 각 문서 "_id"에서 "처음"과 "마지막" "$ 티커"필드 값보다는 :

마지막 경우

, 당신은 당신이 제공 한 데이터에 의하면,이 같은 것을 얻을 것이다 :

{ 
    "_id" : ObjectId("53d1340478441a1c0d25c40c"), 
    "ticker" : "OM:A1M", 
    "items" : [ 
      { 
        "date" : ISODate("2014-07-21T22:09:20Z"), 
        "value" : 10, 
        "_id" : ObjectId("53d134048b3956000063aa71") 
      }, 
      { 
        "date" : ISODate("2014-07-22T22:18:05Z"), 
        "value" : 4, 
        "_id" : ObjectId("53d134048b3956000063aa72") 
      } 
    ] 
} 

당신은 설명서의 Full List of Aggregation Operators을 찾을 수 있습니다. 집계 프레임 워크를 수행하는 기능에 따라 이러한 기능이 매우 유용한 도구가 될 수있는 방법을 알면 가치가 있습니다.

관련 문제