2014-07-22 3 views
1

그래서 각 연령대의 사람 수를 반환하는 쿼리를 작성합니다 - 증가하지 않습니다. 1, 2, 3, ... 67 ... 99, ... 년 동안 살아 있었던 사람들의 수.간격없이 연령대를 선택

NoSQL에 익숙하지 않지만 시간이 오래 되었기 때문에 나이 수를 주기적으로 업데이트/새로 고쳐야한다는 것을 알고 있습니다. 제가 생각한 것은 나이 인 사람들의 수와 나이와 가치의 열쇠를 가진 콜렉션 또는 무언가를 갖는 것입니다. 새로운 사람이 만들어지면 나이에 맞는 사람들의 양이 증가 할 것입니다.

내가 알아 내려고하는 것은 카운터가 없어도 모든 연령대의 사람들 (실시간)을 적극적으로 가져올 수있는 방법이 있는지입니다. 또는 카운터를 사용해야하는 경우 데이터베이스와 카운터를 자동으로 증가시켜 프로그램과 상호 작용할 필요가 없습니다.

+0

지도를 사용하고 싶습니다./여기에서 줄이십시오. 집계 프레임 워크에는 공개 티켓이 있지만 아직 해결되지 않았습니다. – kwolfe

+0

사람 문서는 어떻게 보이나요? 그 사람의 나이가있는 분야가 있습니까? 그리고이 사람들 모두가 하나의 컬렉션에 있다고 가정합니다. –

+0

@JuanCarlosFarah Sorta, 모든 사람들이 데이트 필드로 생년월일을 가진 콜렉션에 있습니다. – Hans

답변

2

MongoDB의 집계 프레임 워크를 사용하여이를 수행 할 수 있습니다. 실시간으로 최신으로 유지하기 위해, 당신이해야 할 것은 다음이다 :

  1. 프로젝트 현재 날짜로부터 출생 (dob)의 날짜를 차감하여 ageMillis 필드. 연령 값은 밀리 초 단위로 표시됩니다.
  2. ageMillis을 1 년 (자바 스크립트의 경우 31536000000)으로 나누고 ageDecimal 필드에 투영하십시오. 이 연령에 그룹화하려면 십진법을 사용하고 싶지 않습니다.
  3. ageDecimal 필드와 십진수 부분을 포함하는 decimal 필드를 투영하십시오. $mod 연산자를 사용하여이 작업을 수행 할 수 있습니다.
  4. decimal에서 ageDecimal을 뺀 다음 age 필드로 투사하십시오. 이것은 당신에게 년의 나이 값을 제공합니다.
  5. 그룹 age 필드로 그룹화하고 $sum을 사용하여 카운트를 추적하십시오. 기본적으로 그 나이에 볼 수있는 모든 문서에 대해 1을 더합니다.
  6. 필요한 경우 age 필드로 정렬하십시오.

셸의 명령은 아래 명령과 같습니다. JavaScript의 Date() 개체를 사용하여 현재 날짜를 가져옵니다. Ruby에서이 작업을 수행하려면 해당 코드를 변경하고 나머지는 Ruby 드라이버의 구문을 따라야합니다.

db.collection.aggregate([ 
    { "$project" : 
     { 
      "ageMillis" : { "$subtract" : [ new Date(), "$dob" ]} 
     } 
    }, 
    { "$project" : 
     { 
      "ageDecimal" : { "$divide" : [ "$ageMillis", 31536000000 ]} 
     } 
    }, 
    { "$project" : 
     { 
      "ageDecimal" : "$ageDecimal", 
      "decimal" : { "$mod" : [ "$ageDecimal", 1 ]} 
     } 
    }, 
    { "$project" : 
     { 
      "age" : { "$subtract" : [ "$ageDecimal", "$decimal" ]} 
     } 
    }, 
    { "$group" : 
     { 
      "_id" : { "age" : "$age" }, 
      "count" : { "$sum" : 1 } 
     } 
    }, 
    { "$sort" : 
     { 
      "_id.age" : 1 
     } 
    } 
]); 

이렇게하면 원하는 결과를 얻을 수 있습니다. aggregate() 메서드는 커서를 반환합니다. 결과를 얻기 위해 반복해야합니다.

+0

수학은 바로 여기에 있습니다.하지만 이처럼 $ project를 사용해서는 안됩니다. 읽는 것이 쉬운 것처럼 보일 수도 있지만, MongoDB에게 많은 불필요한 작업을하도록 요청하고 있습니다. 각 $ 프로젝트는 전체 컬렉션을 단일 패스로 생각하십시오. 따라서 이것이 그룹 $ 1 단계에서 수행 될 수없는 이유는 없습니다. 루비 드라이버는 커서와 배열의 사용을 상당히 용서하고 있으며 거의 ​​동일하게 취급됩니다. 공정한 노력 +1. 나는 단지 다른 부분들을 설명하기 위해 추가했다. –

+0

@ NeilLunn, 의견 주셔서 감사합니다! 너가 확실히 맞아. '$ group' 단계에서 모든 수학을 수행하는 것이보다 효과적이고 간결한 해결책입니다. –

1

집합 프레임 워크가이를위한 최상의 방법입니다. Mongoid는 하위 레벨 컬렉션 객체를 .collection 접근자를 통해 노출합니다. 이를 통해 네이티브 드라이버 구현을 사용할 수 있습니다.

기본 수학은 여기에 있습니다 :

의 둥근 결과 : (1 년에 밀리 이제 밀리 초/ 번호 생년월일에서 차이)

현재 Time 피드 집계 계산서에 값을 입력하여 현재 나이를 얻으십시오.

res = Model.collection.aggregate([ 
    { "$group" => { 
    "_id" => { 
     "$subtract" => [ 
     { "$divide" => [ 
      { "$subtract" => [ Time.now, "$dob" ] }, 
      31536000000 
     ]}, 
     { "$mod" => [ 
      { "$divide" => [ 
      { "$subtract" => [ Time.now, "$dob" ] }, 
      31536000000 
      ]}, 
      1 
     ]} 
     ] 
    }, 
    "count" => { "$sum" => 1 } 
    }}, 
    { "$sort" => { "_id" => -1 } } 
]) 

pp res 
관련 문제