MongoDB의 레코드 수 계산

Tahseen Tauseef 2024년2월15일
  1. MongoDB의 작업
  2. MongoDB의 집계 작업
  3. MongoDB의 $count
  4. MongoDB의 db.collection.count()
  5. 개수로 MongoDB 그룹화
  6. 카운트 정렬 기준 MongoDB 그룹화
  7. 여러 필드를 계산하여 MongoDB 그룹화
  8. 날짜 및 개수로 MongoDB 그룹화
  9. MongoDB의 .toArray() 메소드
  10. MongoDB의 .itcount()
MongoDB의 레코드 수 계산

이 기사에서는 MongoDB의 연산자, 집계 연산자 및 총 레코드 수를 계산하는 다양한 방법에 대해 설명합니다.

MongoDB의 작업

CRUD 작업은 사용자가 데이터베이스에서 개체를 탐색, 검색 및 변경할 수 있도록 하는 사용자 인터페이스의 개념입니다.

MongoDB 문서는 서버에 연결하고 적절한 문서를 쿼리한 다음 해당 데이터를 처리할 데이터베이스로 다시 보내기 전에 변환하여 변경됩니다. CRUD는 HTTP 작업 동사를 사용하여 표준화하는 데이터 기반 프로세스입니다.

  1. 만들기 - MongoDB 데이터베이스에 새 문서를 삽입하는 데 사용됩니다.
  2. 읽기 - 데이터베이스에서 문서를 쿼리하는 데 사용됩니다.
  3. 업데이트 - 데이터베이스의 기존 문서를 수정하는 데 사용됩니다.
  4. 삭제 - 데이터베이스에서 문서를 제거합니다.

MongoDB의 집계 작업

단일 결과를 생성하기 위해 그룹화된 데이터에 대해 많은 작업을 수행하는 단계로 구성된 데이터 처리 작업입니다. 다음은 집계 작업을 수행하기 위한 세 가지 옵션입니다.

  1. 집계를 위한 파이프라인 - 문서는 다단계 파이프라인을 통해 제공되어 하나의 출력으로 통합됩니다. MongoDB 집계 프로세스는 여러 단계로 나뉩니다.

    아래에 예가 나와 있습니다.

    db.collection_name.aggregate([
    
       //First stage
       { $match: { status: "" } },
    
       //Second stage
       { $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
    
       //Third Stage
    	{ $sort : {sort_field: -1 }}
    
    ])
    
  2. 단일 목적 집계 방법 - 단일 목적 집계 방법은 간단하지만 집계 파이프라인의 기능이 부족합니다.

  3. Map-Reduce - Map-Reduce 작업은 MongoDB 5.0부터 더 이상 사용되지 않습니다. 대신 집계 파이프라인을 사용하세요.

MongoDB의 $count

수신한 레코드 수와 함께 문서를 다음 단계로 보냅니다.

행동:

다음 $group + $project 시퀀스는 $count 단계와 같습니다.

db.collection.aggregate( [
   { $group: { _id: null, myCount: { $sum: 1 } } },
   { $project: { _id: 2 } }
] )

myCount가 나타내는 경우 출력 필드에 개수가 포함됩니다. 출력 필드에 다른 이름을 지정할 수 있습니다.

예:

scores라는 콜렉션에는 주어진 문서가 있습니다.

{ "_id" : 1, "subject" : "English", "score" : 88 }
{ "_id" : 2, "subject" : "English", "score" : 92 }
{ "_id" : 3, "subject" : "English", "score" : 97 }
{ "_id" : 4, "subject" : "English", "score" : 71 }
{ "_id" : 5, "subject" : "English", "score" : 79 }
{ "_id" : 6, "subject" : "English", "score" : 83 }

다음 집계 작업에는 두 단계가 있습니다.

  1. $match 단계는 score 값이 80보다 작거나 같은 문서를 필터링하여 score80보다 큰 문서가 다음 단계로 이동할 수 있도록 합니다.
  2. $count 단계는 집계 파이프라인에 남아 있는 문서 수를 계산하고 그 결과를 passing_scores라는 변수에 저장합니다.
db.scores.aggregate(
  [
    {
      $match: {
        score: {
          $gt: 80
        }
      }
    },
    {
      $count: "passing_scores"
    }
  ]
)

이 작업은 다음 결과를 반환합니다.

{ "passing_scores" : 4 }

1000개의 레코드를 가져오려면 평균 2ms가 걸리며 가장 빠른 방법입니다.

MongoDB의 db.collection.count()

find() 쿼리와 일치하는 컬렉션 또는 뷰의 레코드 수를 반환합니다. db.collection.count() 함수는 find() 프로시저가 아닌 쿼리와 일치하는 결과 수를 세고 제공합니다.

행동:

트랜잭션에서는 count 또는 쉘 도구 count()db.collection.count()를 사용할 수 없습니다.

샤드 클러스터

고아 문서가 있거나 청크 마이그레이션이 진행 중인 경우 샤딩된 클러스터에서 쿼리 조건자 없이 db.collection.count()를 사용하면 잘못된 계산이 발생할 수 있습니다.

이러한 상황을 방지하려면 샤드 클러스터에서 db.collection.aggregate() 함수를 사용하십시오.

문서를 계산하려면 $count 단계를 사용하십시오. 예를 들어 다음 절차는 컬렉션의 문서 수를 계산합니다.

db.collection.aggregate( [
   { $count: "myCount" }
])

$count 단계는 다음 $group + $project 시퀀스와 같습니다.

db.collection.aggregate( [
   { $group: { _id: null, count: { $sum: 1 } } }
   { $project: { _id: 0 } }
] )

인덱스 사용

다음 인덱스가 있는 컬렉션을 고려하십시오.

{ a: 1, b: 1 }

카운트를 수행할 때 MongoDB는 쿼리가 다음과 같은 경우에만 인덱스를 사용하여 카운트를 반환할 수 있습니다.

  1. 인덱스를 사용할 수 있습니다.
  2. 인덱스의 키에 대한 조건만 포함하고,
  3. 색인 키의 단일 연속 범위에 대한 액세스를 예측합니다.

예를 들어 인덱스만 지정된 경우 다음 프로시저는 개수를 반환할 수 있습니다.

db.collection.find( { a: 5, b: 5 } ).count()
db.collection.find( { a: { $gt: 5 } } ).count()
db.collection.find( { a: 5, b: { $gt: 10 } } ).count()

쿼리가 인덱스를 사용할 수 있지만 술어가 인덱스 키의 단일 연속 범위에 도달하지 않는다고 가정합니다. 쿼리에는 인덱스 외부의 필드에 대한 조건도 있습니다.

이 경우 MongoDB는 인덱스를 활용하여 개수를 제공하는 것 외에도 문서를 읽어야 합니다.

db.collection.find( { a: 6, b: { $in: [ 1, 2, 3 ] } } ).count()
db.collection.find( { a: { $gt: 6 }, b: 5 } ).count()
db.collection.find( { a: 5, b: 5, c: 8 } ).count()

이러한 상황에서 MongoDB는 초기 읽기 중에 문서를 메모리로 페이징하여 동일한 카운트 작업에 대한 후속 호출 속도를 향상시킵니다.

예기치 않은 종료 시 정확도

count()에서 제공하는 카운트 통계는 Wired Tiger 스토리지 엔진을 사용하는 mongod를 부정확하게 종료한 후 오류가 발생할 수 있습니다.

마지막 검사점과 비정상적인 종료 사이에 실행된 삽입, 업데이트 또는 삭제 작업의 수에 따라 드리프트의 양이 결정됩니다.

체크포인트는 평균 60초마다 발생합니다. 반면에 기본값이 아닌 -syncdelay 옵션이 있는 mongod 인스턴스에는 체크포인트가 많거나 적을 수 있습니다.

비정상적인 종료 후 통계를 복원하려면 mongod의 각 컬렉션에서 validate를 실행하십시오.

불결한 종료 후:

  1. validatecollStats 출력의 카운트 통계를 최신 값으로 업데이트합니다.
  2. collStats 출력에 삽입되거나 제거된 문서 수와 같은 기타 통계는 추정치입니다.

클라이언트 연결 해제

MongoDB 4.2부터 db.collection.count()를 실행한 클라이언트가 작업이 완료되기 전에 연결을 끊는 경우 MongoDB는 killOp를 사용하여 종료에 대해 db.collection.count()를 표시합니다.

컬렉션의 모든 문서 계산

orders 컬렉션의 모든 레코드 수를 계산하려면 다음 작업을 사용합니다.

db.orders.count()

이 작업은 다음과 같습니다.

db.orders.find().count()

쿼리와 일치하는 모든 문서 계산

orders 컬렉션에서 new Date('01/01/2012')보다 큰 ord_dt 필드가 있는 문서 수를 계산합니다.

db.orders.count( { ord_dt: { $gt: new Date('01/01/2012') } } )

쿼리는 다음과 동일합니다.

db.orders.find( { ord_dt: { $gt: new Date('01/01/2012') } } ).count()

개수로 MongoDB 그룹화

MongoDB에 있는 각 문서의 _id 열에는 값별로 고유한 그룹이 할당되었습니다. 그런 다음 집계 기술이 데이터를 처리하여 계산된 결과를 생성합니다.

다음은 예입니다. 데이터베이스 설정은 여기에서 볼 수 있습니다.

이 설정은 이 문서에 제시된 모든 코드 샘플에서 활용됩니다.

db={
  "data": [
    {
      "_id": ObjectId("611a99100a3322fc1bd8c38b"),
      "fname": "Tom",
      "city": "United States of America",
      "courses": [
        "c#",
        "asp",
        "node"
      ]
    },
    {
      "_id": ObjectId("611a99340a3322fc1bd8c38c"),
      "fname": "Harry",
      "city": "Canada",
      "courses": [
        "python",
        "asp",
        "node"
      ]
    },
    {
      "_id": ObjectId("611a99510a3322fc1bd8c38d"),
      "fname": "Mikky",
      "city": "New Zealand",
      "courses": [
        "python",
        "asp",
        "c++"
      ]
    },
    {
      "_id": ObjectId("611b3e88a60b5002406571c3"),
      "fname": "Ron",
      "city": "United Kingdom",
      "courses": [
        "python",
        "django",
        "node"
      ]
    }
  ]
}

사용된 위 데이터베이스에 대한 쿼리는 다음과 같습니다.

db.data.aggregate([
  {
    $group: {
      _id: "ObjectId",
      count: {
        $count: {}
      }
    }
  }
])

위 실행에 대한 링크는 이 코드 세그먼트의 작동을 보기 위해 제공됩니다.

그룹별

카운트 정렬 기준 MongoDB 그룹화

이 섹션에서는 $sortByCount가 사용되며 $group + $sort와 동일합니다. 오름차순 및 내림차순으로 사람들의 그룹을 정렬하고 계산할 수 있습니다.

예제 쿼리는 다음과 같습니다. 이 예에서는 일부 문서가 데이터 수집에 추가되었으며 find() 메서드는 포함된 항목 수를 결정하는 데 사용됩니다.

다음은 find()에 대한 쿼리입니다.

db.data.find()

링크에서 이 쿼리 실행에 액세스할 수 있습니다.

다음 단계는 코스 배열을 실행 취소하고 $sortByCount 함수를 사용하여 각 코스에 추가된 레코드 수를 계산하는 것입니다.

db.data.aggregate([
  {
    $unwind: "$courses"
  },
  {
    $sortByCount: "$courses"
  }
])

위의 데이터베이스 구성으로 이 쿼리가 작동하는 것을 볼 수 있는 링크가 여기에 제공됩니다. 이것은 배열을 세고 정렬하는 MongoDB 그룹에 대한 가장 간단한 접근 방식입니다.

그룹별 2

여러 필드를 계산하여 MongoDB 그룹화

MongoDB의 aggregate() 함수는 여러 필드를 계산할 수 있습니다. 결과적으로 필드는 $count를 사용하여 계산됩니다.

다음은 타임스탬프가 하나의 항목에만 사용되는 예입니다. 이 예제에서 일부 문서는 student 컬렉션에 저장할 수 있으며 find() 메서드를 사용하여 얼마나 많은 문서가 있는지 확인할 수 있습니다.

db.student.aggregate([ {$group: {_id: {name:"$name",
                                         timestamp:"$timestamp" }}},
                                        {$count:"timestamp"}
                      ])

이 쿼리의 실행은 이 링크에서 액세스할 수 있습니다.

날짜 및 개수로 MongoDB 그룹화

특정 날짜 문서를 집계해야 하는 경우 집계 집계를 활용하여 특정 날짜 문서를 집계할 수 있습니다.

여기 삽화가 있습니다. 이 예에서는 2021년의 일별 전체 판매 금액 및 판매 건수를 계산하는 방법을 배웁니다.

판매 컬렉션에 제품 ID, 품목 이름, 가격, 수량날짜 필드를 포함할 수 있습니다. 문서는 find() 메서드를 사용하여 얻을 수 있습니다.

db=
{
        "_id" : 1,
        "item" : "abc",
        "price" : NumberDecimal("10"),
        "quantity" : 2,
        "date" : ISODate("2021-03-01T08:00:00Z")
}
{
        "_id" : 2,
        "item" : "jkl",
        "price" : NumberDecimal("20"),
        "quantity" : 1,
        "date" : ISODate("2021-03-01T09:00:00Z")
}
{
        "_id" : 3,
        "item" : "xyz",
        "price" : NumberDecimal("5"),
        "quantity" : 10,
        "date" : ISODate("2021-03-15T09:00:00Z")
}
{
        "_id" : 4,
        "item" : "xyz",
        "price" : NumberDecimal("5"),
        "quantity" : 20,
        "date" : ISODate("2021-04-04T11:21:39.736Z")
}
{
        "_id" : 5,
        "item" : "abc",
        "price" : NumberDecimal("10"),
        "quantity" : 10,
        "date" : ISODate("2021-04-04T21:23:13.331Z")
}

위 구성에 대한 쿼리는 다음과 같습니다.

db.date.aggregate([
  {
    $match : { "date": { $gte: new ISODate("2021-01-01"), $lt: new ISODate("2015-01-01") } }
  },

  {
    $group : {
       _id : { $dateToString: { format: "%Y-%m-%d", date: "$date" } },
       totalSaleAmount: { $sum: { $multiply: [ "$price", "$quantity" ] } },

       count: { $sum: 1 }
    }
  },
  {
    $sort : { totalSaleAmount: -1 }
  }
 ])

이제 countfield 명령을 사용하여 단일 필드 및 여러 필드 그룹에 대한 쿼리가 아래에 제공됩니다.

  1. 단일 필드 그룹화 기준 및 개수

    db.Request.aggregate([{'$group': {_id: '$source', count: {$sum: 1}}}])
    
  2. 여러 필드 그룹화 기준 및 개수

    db.Request.aggregate([
      {'$group': {_id: {source: '$source', status: '$status'}, count: {$sum: 1}}}
    ])
    
  3. 필드를 사용하여 정렬하여 여러 필드를 그룹화하고 계산합니다.

    db.Request.aggregate([
      {'$group': {_id: {source: '$source', status: '$status'}, count: {$sum: 1}}},
      {$sort: {'_id.source': 1}}
    ])
    
  4. 카운트를 사용하여 정렬하여 여러 필드 그룹화 및 카운트

    db.Request.aggregate([
      {'$group': {_id: {source: '$source', status: '$status'}, count: {$sum: 1}}},
      {$sort: {'count': -1}}
    ])
    

MongoDB의 .toArray() 메소드

toArray() 함수는 커서에 있는 모든 문서를 포함하는 배열을 반환합니다. 절차는 커서를 여러 번 반복하여 모든 문서를 RAM에 로드하고 포인터를 고갈시킵니다.

toArray() 함수를 사용하여 find() 메서드에서 반환된 커서를 변환하는 다음 예제를 고려하십시오.

var allProductsArray = db.products.find().toArray();

if (allProductsArray.length > 0) {
  printjson(allProductsArray[0]);
}

allProductsArray 변수는 toArray()에 의해 반환된 문서 배열을 보유합니다. 1000개의 레코드를 가져오려면 평균 18ms가 걸립니다.

MongoDB의 .itcount()

커서에 남아 있는 문서 수를 계산합니다.

itcount()cursor.count()와 유사하지만 새 반복자에서 쿼리를 실행하는 대신 기존 반복자에서 실행하여 내용을 소진합니다.

itcount() 메서드의 프로토타입 형식은 다음과 같습니다.

db.collection.find(<query>).itcount()

1000개의 레코드를 가져오려면 평균 14ms가 걸립니다.

이 문서에서는 작업에 대해 자세히 설명했으며 집계 작업에 대해서도 설명했습니다. 먼저 다양한 유형의 집계 함수가 코드 세그먼트와 함께 간략하게 논의되었습니다.

그런 다음 정렬, 찾기 및 여러 필드에 대해 논의한 그룹 기준 및 개수에 대해 논의했습니다. 그런 다음 MongoDB에서 레코드를 계산하는 다양한 방법에 대해 설명합니다.

관련 문장 - MongoDB Record