MongoDB에서 배열 크기가 1보다 큰 문서 쿼리

Tahseen Tauseef 2023년6월20일
  1. 샘플 데이터
  2. $size 연산자를 사용하여 MongoDB에서 배열 크기가 1보다 큰 문서 쿼리
  3. $where 연산자를 사용하여 MongoDB에서 배열 크기가 1보다 큰 문서 쿼리
  4. 점 표기법을 사용하여 MongoDB에서 배열 크기가 1보다 큰 문서 쿼리
  5. $expr(3.6+)을 사용하여 MongoDB에서 배열 크기가 1보다 큰 문서 쿼리
  6. 집계 $facet 연산자를 사용하여 MongoDB에서 배열 크기가 1보다 큰 문서 쿼리
MongoDB에서 배열 크기가 1보다 큰 문서 쿼리

배열 크기를 확인하거나 크기가 특정 길이보다 크거나 작은 요소를 찾아야 하는 프로젝트에서 작업할 때 $size, $where, $exists와 같은 MongoDB 연산자를 사용할 수 있습니다.

아래에 설명된 접근 방식은 어레이 길이 또는 어레이 크기 문제를 해결하는 데 도움이 될 수 있습니다.

샘플 데이터

다음 데이터가 있다고 가정합니다. 이 샘플 데이터를 사용하여 MongoDB에서 특정 배열 크기의 문서를 쿼리합니다.

db.inventory.insertMany([

{ item: "journal", qty: 25, tags: ["blank", "reds"], book: { author:`xyz`, price:50, location:[`india`, `USA`, `nepal`]} },

{ item: "notebook", qty: 50, tags: ["reds", "blank"], book: { author:`xyz`, price:50, location:[`india`, `usa`]} },

{ item: "paper", qty: 100, tags: ["reds", "blank", "plain"], book: { author:`xyz`, price:50, location:[]}},
{ item: "planner", qty: 75, tags: ["blank", "reds"], book: { author:`xyz`, price:50, location:[`india`]} },

{ item: "postcard", qty: 45, tags: ["blue"], book:{} }
]);

$size 연산자를 사용하여 MongoDB에서 배열 크기가 1보다 큰 문서 쿼리

MongoDB의 배열 연산자 클래스는 배열을 참조하여 문서를 얻는 데 사용되는 많은 연산자로 구성됩니다. $size도 그 중 하나입니다. $size 연산자는 특정 크기의 배열 필드를 포함하는 문서를 가져오는 데 사용됩니다.

배열에서만 작동하며 숫자 값을 매개변수로 허용합니다.

다음은 $size 연산자의 기본 기능입니다.

  1. 배열 필드를 사용자가 지정한 크기와 비교하여 시작한 다음 계속됩니다.
  2. 이전 단계를 수행하는 필드가 포함된 문서를 검색합니다.

통사론:

{array-field: {$size: <length-of-array>}}

이 경우 array-field는 문서에서 원하는 필드의 이름이고 length-of-array는 길이와 일치하는 숫자입니다.

MongoDB에서 $size 연산자를 사용하는 방법을 볼 수 있는 몇 가지 예가 아래에 공유되어 있습니다.

태그 길이가 1인 요소 찾기

db.inventory.find({tags:{$size:1}})

출력:

$size 1

books.location 길이가 1인 요소 찾기

db.inventory.find({books.location:{$size:1}}

출력:

$size 2

$where 연산자를 사용하여 MongoDB에서 배열 크기가 1보다 큰 문서 쿼리

쿼리 시스템에 JavaScript 표현식 또는 전체 JavaScript 함수를 포함하는 문자열을 제공하려면 $where 연산자를 사용하십시오. 더 많은 유연성을 허용하지만 컬렉션의 모든 문서에 대해 JavaScript 표현식 또는 기능을 수행하려면 데이터베이스가 필요합니다.

this 또는 obj를 사용하여 JavaScript 표현식 또는 함수의 레코드를 참조하십시오.

통사론:

{ $where: <string|JavaScript Code> }

$where 연산자의 작업을 보여주기 위한 예제가 아래에 제공됩니다.

태그 길이가 1인 요소 찾기

db.inventory.find({tags:{$where:`this.tags.length == 1`}}

출력:

$where 1

태그 길이가 1보다 크거나 같은 요소 찾기

db.inventory.find({tags:{$where:`this.tags.length >= 1`}}

books.location 길이가 1인 요소 찾기

you cannot check this with the help of $where

$where 쿼리 연산자는 최상위 문서에서만 사용하십시오. 중첩된 페이지 내에서는 작동하지 않습니다.

점 표기법을 사용하여 MongoDB에서 배열 크기가 1보다 큰 문서 쿼리

포함된 문서의 배열 요소 및 필드에 액세스하기 위해 MongoDB는 점 표기법을 사용합니다.

배열 요소에 액세스

0부터 시작하는 인덱스 위치로 배열 요소를 지정하거나 액세스하려면 배열 이름을 점(.) 및 0부터 시작하는 인덱스 위치와 연결한 다음 따옴표로 묶습니다.

통사론:

"<array>.<index>"

예를 들어 문서의 다음 필드를 고려하십시오.

{
   ...
   contribs: [ "Turing machine", "Turing test", "Turingery" ],
   ...
}

점 표기법 "contribs.2"를 사용하여 contribs.2 배열에서 세 번째 구성원을 식별합니다.

태그 길이가 0보다 큰 요소 찾기

db.inventory.find({tags.0:{$exists:true`}}
It will look for elements with at least one tag // array with a zero-based index.

books.location 길이가 1보다 큰 요소 찾기

db.invantory.find({book.location.1: {$exists:true}}
// It looks for all components in whose book. There are at least two elements to a place.

$expr(3.6+)을 사용하여 MongoDB에서 배열 크기가 1보다 큰 문서 쿼리

통사론:

{ $expr: { <expression> } }

$tags 길이가 0보다 큰 문서 찾기

db.invantory.find({
    $expr: {
        $gt: [{ $size: { $ifNull: ["$tags", []] } }, 0]
    }
})

$books.location 길이가 1보다 큰 요소 찾기

db.invantory.find({
    $expr: {
        $gt: [{ $size: { $ifNull: ["$book.location", []] } }, 1]
    }
})
// $ifNull: ["$book.location", []] this is used to avoid any error if book.location is null

집계 $facet 연산자를 사용하여 MongoDB에서 배열 크기가 1보다 큰 문서 쿼리

이 연산자는 단일 단계에서 동일한 입력 문서 세트에 대한 수많은 집계를 처리합니다. 각 파이프라인에는 결과가 문서 배열로 저장되는 출력 문서에 해당 필드가 있습니다.

$facet 단계를 사용하면 단일 집계 단계 내에서 여러 차원 또는 패싯에 걸쳐 데이터를 특성화하는 다면 집계를 생성할 수 있습니다. 다면적 집계는 데이터 검색 및 분석을 돕기 위해 여러 필터 및 분류를 제공합니다.

예를 들어 소매업체는 패싯을 사용하여 제품 가격, 제조업체, 크기 등을 기반으로 필터를 만들어 검색 결과를 줄이는 경우가 많습니다.

입력 문서는 $facet 단계로 한 번만 전송됩니다. $facet를 사용하면 여러 번 검색할 필요 없이 동일한 입력 문서 세트에 대한 수많은 집계가 가능합니다.

통사론:

{ $facet:
   {
      <outputField1>: [ <stage1>, <stage2>, ... ],
      <outputField2>: [ <stage1>, <stage2>, ... ],
      ...

   }
}

각 파이프라인의 출력 필드 이름을 입력합니다.

$facet의 각 하위 파이프라인은 동일한 입력 문서 세트를 수신합니다. 이러한 하위 파이프라인은 서로 독립적이며 각각에 의해 생성된 문서 배열은 출력 문서의 다른 필드에 저장됩니다.

동일한 $facet 단계 내에서 한 하위 파이프라인의 출력을 다른 하위 파이프라인의 입력으로 사용할 수 없습니다. $facet 뒤에 추가 단계를 추가하고 추가 집계가 필요한 경우 원하는 하위 파이프라인 출력의 필드 이름 outputField>를 표시합니다.

$facet 단계에서 인덱스 사용

하위 파이프라인이 $match를 활용하거나 $facet가 파이프라인의 초기 단계인 경우에도 $facet 단계와 해당 하위 파이프라인은 인덱스를 사용할 수 없습니다. 실행 중에 $facet 단계는 항상 COLLSCAN을 수행합니다.

재고가 다음 삽화 컬렉션에 저장되어 있는 온라인 상점을 고려하십시오.

{ "_id" : 1, "title" : "The Pillars of Society", "artists" : "Grosz", "year" : 1926,
  "price" : NumberDecimal("199.99"),
  "tags" : [ "painting", "satire", "Expressionism", "caricature" ] }
{ "_id" : 2, "title" : "Melancholy III", "artists" : "Munch", "year" : 1902,
  "price" : NumberDecimal("280.00"),
  "tags" : [ "woodcut", "Expressionism" ] }
{ "_id" : 3, "title" : "Dancer", "artists" : "Miro", "year" : 1925,
  "price" : NumberDecimal("76.04"),
  "tags" : [ "oil", "Surrealism", "painting" ] }
{ "_id" : 4, "title" : "The Great Wave off Kanagawa", "artists" : "Hokusai",
  "price" : NumberDecimal("167.30"),
  "tags" : [ "woodblock", "ukiyo-e" ] }
{ "_id" : 5, "title" : "The Persistence of Memory", "artist" : "Dali", "year" : 1931,
  "price" : NumberDecimal("483.00"),
  "tags" : [ "Surrealism", "painting", "oil" ] }
{ "_id" : 6, "title" : "Composition VII", "artist" : "Kandinsky", "year" : 1913,
  "price" : NumberDecimal("385.00"),
  "tags" : [ "oil", "painting", "abstract" ] }
{ "_id" : 7, "title" : "The Scream", "artist" : "Munch", "year" : 1893,
  "tags" : [ "Expressionism", "painting", "oil" ] }
{ "_id" : 8, "title" : "Blue Flower", "artist" : "O`Keefe", "year" : 1918,
  "price" : NumberDecimal("118.42"),
  "tags" : [ "abstract", "painting" ] }

다음 절차는 MongoDB의 패싯 기능을 활용하여 소비자에게 태그, 가격 및 생성 연도로 구성된 매장의 재고를 보여줍니다. 이 $facet 단계는 $sortByCount, $bucket 또는 $bucketAuto.를 사용하여 이 다각적인 집계를 수행하는 세 개의 하위 파이프라인으로 구성됩니다.

artwork의 입력 문서는 작업 시작 시 데이터베이스에서 한 번만 검색됩니다.

예:

db.artwork.aggregate( [
  {
    $facet: {
      "categorizedByTags": [
        { $unwind: "$tags" },
        { $sortByCount: "$tags" }
      ],
      "categorizedByPrice": [
        // Filter out documents without a price e.g., _id: 7
        { $match: { price: { $exists: 1 } } },
        {
          $bucket: {
            groupBy: "$price",
            boundaries: [  0, 150, 200, 300, 400 ],
            default: "Other",
            output: {
              "count": { $sum: 1 },
              "titles": { $push: "$title" }
            }
          }
        }
      ],
      "categorizedByYears(Auto)": [
        {
          $bucketAuto: {
            groupBy: "$year",
            buckets: 4
          }
        }
      ]
    }
  }
])

출력:

$facet 1

관련 문장 - MongoDB Query