IBM Cloud Docs
보기 작성(MapReduce)

보기 작성(MapReduce)

보기는 데이터베이스 내에 저장된 데이터를 가져오기 위해 사용됩니다. 뷰 내에서는 감축 함수, 맵 및 감축 함수, 그리고 뷰 정의 저장을 사용합니다.

가장 단순한 보기, reduce 함수, map 및 reduce 함수 제한사항과 보기 정의를 저장하는 방법에 대한 정보를 참조하십시오. 제공되는 예제도 참조하십시오. 보기는 JavaScript를 사용하여 작성됩니다.

보기 개념

보기는 데이터베이스의 문서 컨텐츠 관련 작업을 수행하기 위한 메커니즘입니다. 보기는 문서를 선택적으로 필터링하고 콘텐츠 검색 속도를 높일 수 있습니다. 클라이언트로 리턴되기 전에 결과를 사전 처리하는 데 사용할 수 있습니다.

보기는 디자인 문서의 views 필드 내에 정의된 단순한 JavaScript 함수입니다. 보기를 사용하는 경우 또는 더 정확하게는 보기를 사용하여 조회를 실행하는 경우 시스템은 데이터베이스의 모든 문서에 JavaScript 함수를 적용합니다. 보기는 복잡해질 수 있습니다. 필요한 전체 보기를 작성하기 위해 JavaScript 함수의 콜렉션을 정의하도록 선택할 수도 있습니다.

보기 인덱스 파티셔닝 유형

뷰 인덱스는 options.partitioned 필드를 포함하는 디자인 문서의 필드에 추가합니다.

단순 보기

가장 단순한 양식의 보기는 map 함수입니다. map 함수는 데이터베이스 내에 저장된 문서에 대한 분석(맵핑)을 나타내는 출력 데이터를 생성합니다.

예를 들어, 온라인 등록을 완료하고 연락할 확인된 이메일이 있는 사용자를 알고 싶을 수 있습니다. 각 문서를 검색하여 문서에서 "email_verified"라는 필드를 찾고 "email" 값을 가져와서 이 정보를 찾을 수 있습니다. 필드가 존재하고 true, 값이면 사용자가 등록을 완료했음을 의미하며 이메일로 연락할 수 있습니다. 필드가 없거나 true 이외의 다른 값이 있는 경우 사용자가 등록을 완료하지 않은 것입니다.

view 함수에서 emit 함수를 사용하는 경우 보기를 사용하여 조회를 실행하는 작업에 대한 응답에서 간단히 목록을 생성할 수 있습니다. 이 목록은 키 및 값 쌍으로 구성되어 있습니다. 여기서 키는 특정 문서를 식별할 수 있도록 해주며 값은 정확히 원하는 세부사항만 제공합니다. 이 목록에는 리턴되는 key:value 쌍의 수와 같은 메타데이터도 포함되어 있습니다.

문서 _id는 각각의 key:value 쌍 결과 레코드에 자동으로 포함됩니다. 클라이언트에서 더 간단히 결과 관련 작업을 수행할 수 있도록 문서 _id가 포함됩니다.

다음과 같이 map 함수를 사용한 단순 보기 예제를 참조하십시오.

function(user) {
  if(user.email_verified === true) {
    emit(user.email, {name: user.name, email_verified: user.email_verified, joined: user.joined});
  }
}

다음과 같이 단순 보기 예제를 보여주는 샘플 데이터를 참조하십시오.

[
    {
        "_id":"abc123",
        "name": "Bob Smith",
        "email": "bob.smith@aol.com",
        "email_verified": true,
        "joined": "2019-01-24T10:42:59.000Z"
    },
    {
        "_id":"abc125",
        "name": "Amelie Smith",
        "email": "amelie.smith@aol.com",
        "email_verified": true,
        "joined": "2020-04-24T10:42:59.000Z"
    }
]

다음과 같이 단순 보기 조회 실행의 응답 예제를 참조하십시오.

{
  "total_rows": 2,
  "offset": 0,
  "rows": [
    {
      "id": "abc125",
      "key": "amelie.smith@aol.com",
      "value": {
        "name": "Amelie Smith",
        "email_verified": true,
        "joined": "2020-04-24T10:42:59.000Z"
      }
    },
    {
      "id": "abc123",
      "key": "bob.smith@aol.com",
      "value": {
        "name": "Bob Smith",
        "email_verified": true,
        "joined": "2019-01-24T10:42:59.000Z"
      }
    }
  ]
}

Map 함수 예제

또한 디자인 문서 내의 보기 정의는 키 정보를 기반으로 인덱스를 작성합니다. 인덱스를 생성하고 사용하면 액세스 속도와 보기에서 문서를 검색하거나 선택하는 속도가 크게 향상됩니다.

다음 절에서는 단순 및 복합 키를 사용한 인덱싱과 reduce 함수에 대해 설명합니다.

색인화 기능은 문서가 환경에서 사용되는 메모리의 일부를 구성하는 메모리가 제한된 환경에서 작동합니다. 코드의 스택과 문서는 메모리에 맞아야 합니다. 문서를 최대 크기인 64MB로 제한합니다.

필드 인덱싱

다음 map 함수는 오브젝트에 name 필드가 포함되어 있는지 여부를 검사한 후 포함된 경우 이 필드의 값을 생성합니다. 이 검사를 통해 name 필드의 값에 대해 조회할 수 있습니다.

다음과 같이 필드를 인덱싱하는 예제를 참조하십시오.

function(doc) {
  if (doc.name) {
    emit("name", doc.name);
  }
}

일대다 관계에 대한 인덱스

emit로 전달된 오브젝트에 _id 필드가 존재하는 경우 include_docstrue로 설정된 보기 조회에 특정 ID의 문서가 포함되어 있습니다.

다음과 같이 일대다 관계를 인덱싱하는 예제를 참조하십시오.

function(doc) {
  if (doc.friends) {
    for (friend in doc.friends) {
      emit(doc._id, { "_id": friend });
    }
  }
}

복합 키

키는 단순 값으로 제한되지 않습니다. 임의의 JSON 값을 사용하여 정렬에 영향을 미칠 수 있습니다.

키가 배열인 경우 보기 결과를 키의 서브섹션으로 그룹화할 수 있습니다. 예를 들어 키의 양식이 [year, month, day]인 경우 결과를 년, 월 또는 일의 단일 값으로 줄일 수 있습니다.

자세한 정보는 보기 사용을 참조하십시오.

Reduce 함수

options.partitionedtrue로 설정된 디자인 문서에는 사용자 정의 JavaScript reduce 함수를 포함시킬 수 없습니다. 기본 제공 감축만 허용됩니다.

감축자 없음

디자인 문서 내부의 보기 정의에서는 감축 속성이 없는 상태(조회 시간 집계가 수행되지 않음을 나타냄)가 허용됩니다.

{
    "views": {
        "getVerifiedEmails": {
            "map": "function(user) { if(user.email_verified === true) { emit(user.email); } }"
        }
    }
}

이전 map 함수에서는 선택사항에 대해서만 적합한 2차 인덱스를 생성합니다. 인덱스는 항상 키(emit 함수의 첫 번째 매개변수)별로 정렬됩니다. 이 경우에는 user.email입니다. 이 보기는 알려진 사용자 이메일 또는 사용자 이메일 주소 범위로 문서를 페치하는 데 이상적입니다.

기본 제공 reduce 함수

성능상의 이유로 몇 가지 간단한 reduce 함수가 기본 제공됩니다. 가능한 경우 고유한 함수를 작성하지 말고 이러한 함수 중 하나를 사용해야 합니다.

기본 제공 함수 중 하나를 사용하려면 디자인 문서에서 뷰 객체의 reduce 필드에 감속기 이름을 입력합니다.

카운트 감소기

_count 감속기는 MapReduce 뷰의 행을 카운트하고 선택적으로 고유 키별로 카운트를 그룹화합니다.

{
    "views": {
        "teamCount": {
            "map": "function(doc) { if (doc.email_verified === true) { emit(doc.team, doc.name); } }",
            "reduce": "_count"
        }
    }
}

이전 MapReduce 보기는 사용자가 속한 team 에 키가 지정된 인덱스를 생성하지만 이메일 주소가 확인된 사용자만 포함합니다. 감속기는 _count 이므로 뷰는 뷰의 행 수(예: 데이터베이스의 확인된 사용자 수)를 출력합니다.

{"rows":[
{"key":null,"value":10010}
]}

?group=true 을 추가하면 고유 키별로 카운트가 그룹화되어 데이터베이스가 팀 멤버십별로 카운트를 출력합니다:

{"rows":[
{"key":"blue","value":1409},
{"key":"green","value":1439},
{"key":"indigo","value":1425},
{"key":"orange","value":1432},
{"key":"red","value":1414},
{"key":"violet","value":1443},
{"key":"yellow","value":1448}
]}

감속기를 끄면 단일 팀의 구성원 선택에 동일한 보기를 사용할 수 있습니다 ?key="orange"&reduce=false&limit=5:

{"total_rows":10010,"offset":4273,"rows":[
{"id":"783173e102613c78d02a2b3304001642","key":"orange","value":"Bethel Lusk"},
{"id":"783173e102613c78d02a2b3304001b40","key":"orange","value":"Ethyl Dionne"},
{"id":"783173e102613c78d02a2b3304009c66","key":"orange","value":"Fredda Hendrix"},
{"id":"783173e102613c78d02a2b330401800d","key":"orange","value":"Bibi Page"},
{"id":"783173e102613c78d02a2b3304018ae7","key":"orange","value":"Marylou Lavender-Milton"}
]}

합계 감속기

_sum 감속기는 MapReduce 뷰의 방출된 숫자 값을 합산합니다. 뷰의 값은 숫자, 숫자 배열 또는 숫자 값이 포함된 개체일 수 있습니다. 제품 데이터베이스에 대한 다음 MapReduce 정의를 고려하세요:

{
    "views": {
        "productPrices": {
            "map": "function(doc) {  emit(doc.type, { price: doc.price, tax: doc.tax }); }",
            "reduce": "_sum"
        }
    }
}

보기는 제품 유형에 따라 키가 지정되며 값은 pricetax 두 값을 포함하는 개체입니다. _sum 감속기는 뷰 전체에서 pricetax 값의 합계를 계산합니다:

{"rows":[
    {"key":null,"value":{"price":144.97, "tax":7.32}}
]}

뷰를 쿼리할 때 ?group=true 을 추가하면 출력은 고유 키(이 경우 제품 유형)를 기준으로 그룹화되고 합산됩니다:

{"rows":[
    {"key":"kitchen","value":{"price":14.99,"tax":1.14}},
    {"key":"garden","value":{"price":129.98,"tax":6.18}}
]}

통계 감소기

_stats 감속기는 _sum 감속기와 마찬가지로 숫자, 숫자 값 또는 숫자 배열이 있는 객체에 대해 작동하며 개수, 합계, 최소값 및 최대값, 값의 제곱합을 반환하므로 분산 또는 표준편차 계산에 유용합니다:

{
    "views": {
        "salesByDate": {
            "map": "function(doc) { emit(doc.date, [doc.price, doc.tax]); }",
            "reduce": "_stats"
        }
    }
}

이전 정의는 인덱스의 값으로 방출되는 배열에서 찾은 숫자 값에 대한 통계를 계산합니다. 이 값은 map 함수에서 제공된 것과 동일한 순서의 배열로 리턴됩니다.

{"rows":[
    {"key":"2025-01-01","value":[
        {"sum":14.99,"count":1,"min":14.99,"max":14.99,"sumsqr":224.7001},
        {"sum":1.14,"count":1,"min":1.14,"max":1.14,"sumsqr":1.2995}
    ]},
    {"key":"2025-01-02","value":[
        {"sum":129.98,"count":2,"min":29.99,"max":99.99,"sumsqr":10897.4002},
        {"sum":6.18,"count":2,"min":1.62,"max":4.56,"sumsqr":23.418}
    ]}
]}

대략적인 개수 고유 감속기

인덱스 값에 따라 작동하는 숫자 감속기 _sum_stats 와 달리 _approx_count_distinct 감속기는 뷰의 키를 사용합니다. 이 알고리즘은 정확한 고유 카운트 알고리즘이 사용하는 것보다 훨씬 적은 메모리를 사용하는 알고리즘을 사용하여 MapReduce 보기에서 발견된 고유 키의 수를 추정합니다:

{
  "views": {
    "estimateIpCount": {
      "map": "function (doc) {\n  emit(doc.ip, 1);\n}",
      "reduce": "_approx_count_distinct"
    }
  }
}

이전 보기 정의는 서버 로그 데이터베이스에서 고유한 IP 주소의 수를 추정하는 것을 목표로 합니다. _approx_count_distinct 리듀서가 고유 키의 수를 추정할 수 있도록 문서의 ip 이 인덱스의 키로 방출됩니다:

{"rows":[
{"key":null,"value":100528}
]}

상단/하단 감속기

_top_x_bottom_x 감속기(여기서 x 는 1에서 100 사이의 숫자입니다)는 각각 뷰 그룹화에서 상위 x 또는 하위 x 값의 배열을 반환합니다. 예를 들어, 게임 애플리케이션에서 사용자 ID를 키로 하여 사용자가 달성한 점수를 값으로 하는 보기를 만들 수 있습니다. 이 보기를 사용하여 최고 또는 최저 점수로 구성된 점수표를 만들 수 있습니다:

{
    "views": {
        "bestScores": {
            "map": "function(doc) { emit(doc.user_id, doc.score); }",
            "reduce": "_top_3"
        }
    }
}

매개 변수 없이 뷰를 쿼리하면 전체 뷰에서 상위 3개 점수가 반환됩니다:

{"rows":[
  {"key":null,"value":[99,98,97]}
]}

그룹화(?group=true)를 사용하면 각 개별 사용자의 상위 3개 점수가 반환됩니다:

{"rows":[
  {"key":"user082","value":[99,98,97]},
  {"key":"user291","value":[85,72,42]},
  {"key":"user452","value":[55,51,30]}
]}

첫 번째/마지막 감속기

_first/_last 감속기는 각각 뷰 그룹화에서 첫 번째 또는 마지막 키의 값을 반환합니다. IoT 애플리케이션이 여러 디바이스의 판독값을 주기적으로 저장하는 경우, 디바이스 ID와 판독값이 측정된 시간을 키로 하는 보기를 만들 수 있습니다. 뷰의 값은 전체 문서입니다:

{
    "views": {
        "latestReading": {
            "map": "function(doc) { emit([doc.deviceid, doc.timestamp], doc); }",
            "reduce": "_last"
        }
    }
}

이 뷰는 deviceidtimestamp 으로 정렬된 이 형식의 키와 값을 생성합니다. 각 디바이스의 "첫 번째" 및 "마지막" 판독값으로 간주되는 행이 강조 표시됩니다:

첫 번째 읽기 ( group_level=1 ) 마지막 읽기 ( group_level=1 )
["A00","2025-01-01T10:00:00.000Z"] {"_id": "A00:5000","reading": 65,"timestamp":2025-01-01T10:00:00.000Z","deviceid":"A00"} x
["A00","2025-01-01T10:01:00.000Z"] {"_id": "A00:5001","reading": 64,"timestamp":2025-01-01T10:01:00.000Z","deviceid":"A00"}
["A00","2025-01-01T10:02:00.000Z"] {"_id": "A00:5002","reading": 59,"timestamp":2025-01-01T10:02:00.000Z","deviceid":"A00"} x
["A01","2025-01-01T10:00:00.000Z"] {"_id": "A01:8000","reading": 12,"timestamp":2025-01-01T10:00:00.000Z","deviceid":"A01"} x
["A01","2025-01-01T10:01:00.000Z"] {"_id": "A01:8001","reading": 15,"timestamp":2025-01-01T10:01:00.000Z","deviceid":"A01"}
["A01","2025-01-01T10:02:00.000Z"] {"_id": "A01:8002","reading": 19,"timestamp":2025-01-01T10:02:00.000Z","deviceid":"A01"} x
["A02","2025-01-01T10:00:00.000Z"] {"_id": "A02:4000","reading": 55,"timestamp":2025-01-01T10:00:00.000Z","deviceid":"A02"} x
["A02","2025-01-01T10:01:00.000Z"] {"_id": "A02:4001","reading": 54,"timestamp":2025-01-01T10:01:00.000Z","deviceid":"A02"}
["A02","2025-01-01T10:02:00.000Z"] {"_id": "A01:4002","reading": 56,"timestamp":2025-01-01T10:02:00.000Z","deviceid":"A02"} x

_last 리듀서를 사용하여 group_level=1 로 뷰를 쿼리하면 데이터베이스의 모든 device_id에 대한 최신 판독값이 반환됩니다:

{"rows":[
{"key":["A00"],"value":{"_id":"93117567370d41d091b8dd160a3adf3f","_rev":"1-bc05e93e592d5a5a18e240240b581a55","deviceid":"A00","reading":13.8986,"timestamp":"2025-03-26T04:44:08.917Z","status":"red"}},
{"key":["A01"],"value":{"_id":"c9f53ac9e4a8444487ed0eaa11dc1c78","_rev":"1-1fcf121c73db03e49bac4c1981518b19","deviceid":"A01","reading":59.8453,"timestamp":"2025-04-01T01:52:34.254Z","status":"green"}},
{"key":["A02"],"value":{"_id":"577b7108a8a1458f9a17194ed1da398a","_rev":"1-71d345a773ab31f35ceb998f3c107c41","deviceid":"A02","reading":2.6208,"timestamp":"2025-03-31T00:22:17.175Z","status":"green"}},
{"key":["A03"],"value":{"_id":"150839b1d363427496a4f4e2917b8b1d","_rev":"1-860a2ed5f1f48aa642495dfb21dff3ce","deviceid":"A03","reading":55.8677,"timestamp":"2025-03-22T10:15:57.890Z","status":"red"}},
{"key":["A04"],"value":{"_id":"d3317bdc1f7b4466ae6bf7a30ca9e328","_rev":"1-a58762532f6980ca5b06a8d01d113814","deviceid":"A04","reading":44.1822,"timestamp":"2025-03-23T10:56:10.639Z","status":"green"}},
{"key":["A05"],"value":{"_id":"946754d3762f44e297ca20d13bbceb5e","_rev":"1-41fa2bb3ef8782c90b28ee44628abeab","deviceid":"A05","reading":13.2874,"timestamp":"2025-03-27T13:59:04.723Z","status":"blue"}},
{"key":["A06"],"value":{"_id":"bbcd8a5c0ae948baae713a9fcb5262d5","_rev":"1-66883211ee20a0772374672aa175dc50","deviceid":"A06","reading":7.9525,"timestamp":"2025-04-01T15:13:04.305Z","status":"blue"}},
{"key":["A07"],"value":{"_id":"a600caccdb82400698b158ecebfaa6f2","_rev":"1-68975a8d7133a13c6cc8ae34d28ea1c6","deviceid":"A07","reading":89.4818,"timestamp":"2025-03-07T02:12:59.934Z","status":"blue"}},
{"key":["A08"],"value":{"_id":"be20bae911db4da685f891fd01e07d3a","_rev":"1-d69b559627cf01e80fe85ea2f54d2f4b","deviceid":"A08","reading":97.6739,"timestamp":"2025-03-29T13:46:31.689Z","status":"green"}},
{"key":["A09"],"value":{"_id":"96526e80f2ff48e89e9e42aa47abae24","_rev":"1-85e56901f7113d7d6ff8ba573c535eb3","deviceid":"A09","reading":26.1597,"timestamp":"2025-03-18T03:22:19.848Z","status":"blue"}}
]}

기본 제공 감속기 요약

기본 제공 reduce 함수
기능 설명
_count 특정 키에 대한 행 개수를 생성합니다. 값은 임의의 유효한 JSON이 될 수 있습니다.
_stats 합계, 개수, 최소값, 최대값 및 합계 제곱 값이 포함된 JSON 구조를 생성합니다. 모든 값은 숫자여야 합니다 .
_sum 특정 키에 대한 모든 값의 합계를 생성합니다. 값은 숫자여야 합니다.
_approx_count_distinct 뷰 인덱스에서 고유 키의 개수를 근사화합니다 HyperLogLog 알고리즘의 변형을 사용합니다.
_top_x/_bottom_x 뷰 그룹화에서 상위 x 또는 하위 x 값의 배열을 배열로 반환합니다. 여기서 x 은 1에서 100 사이의 숫자입니다.
_first/_last 각 뷰 그룹에 대해 가장 낮거나 가장 높은 정렬 값을 각각 반환합니다.

사용자 정의 reduce 함수

대부분의 고객은 Map 함수에서 생성된 보기 key-value 쌍에 대한 집계를 수행하기 위해 기본 감축자를 사용해도 충분합니다. 하지만 특수한 유스 케이스의 경우 기본 제공 감축자 중 하나의 이름 대신 JavaScript reduce 함수를 제공할 수 있습니다.

사용자 정의 감속 기능은 내장 감속기보다 훨씬 느리고 유지 관리가 어렵기 때문에 사용자 정의 감속기를 작성하기 전에 사용 사례가 내장 감속기로도 만족할 수 있는지 확인하세요.

Reduce 함수는 다음과 같은 순서로 세 개의 인수를 전달합니다.

  • keys
  • values
  • rereduce

보기에 사용자 정의 JavaScript reduce 함수가 포함되어 있는 경우 해당 보기에 대한 집계 결과를 생성하기 위해 사용됩니다. reduce 함수는 중간 값 세트를 전달하고 해당 값 세트를 하나의 값에 결합합니다. reduce 함수의 경우 해당 map 함수를 통해 생성된 결과 뿐만 아니라 reduce 함수 자체에서 리턴하는 결과도 입력으로 승인해야 합니다. 후자의 경우를 "rereduce"라고 합니다.

다음 예제에는 reduce 함수에 대한 설명이 표시되어 있습니다.

사용자 정의 reduce 함수의 다음 예를 참조하십시오.

function (keys, values, rereduce) {
  return sum(values);
}

Reduce 함수에서는 다음과 같은 두 가지 케이스를 처리해야 합니다.

  1. rereduce가 false인 경우:

    • keys는 요소가 [key, id] 양식의 배열인 배열이며, 여기서 key는 맵 함수에 의해 생성된 키이고 id는 키가 생성된 문서를 식별합니다. valueskeys의 각 요소에 대해 생성된 값의 배열입니다(예: reduce([ [key1,id1], [key2,id2], [key3,id3] ], [value1,value2,value3], false)).
  2. rereduce가 true인 경우:

    • keysnull입니다.
    • values는 reduce 함수에 대한 이전 호출에서 리턴된 값의 배열입니다. 예: reduce(null, [intermediate1,intermediate2,intermediate3], true)

Reduce 함수는 최종 보기의 양쪽 value 필드에 적합하며 reduce 함수에 전달되는 values 배열의 멤버로 적합한 단일 값을 리턴해야 합니다.

대체로 reduce 함수는 이전 예의 summation 함수와 같이 추가 코드를 사용하지 않고 rereduce 호출을 처리하는 데 작성될 수 있습니다. 이러한 경우 rereduce 인수를 무시할 수 있습니다.

reduce 함수의 결과를 다시 reduce 함수에 공급하는 경우 MapReduce에서 광범위한 데이터 세트의 분석을 훨씬 더 빠르게 완료할 수 있는 개별 병렬 태스크로 분할할 수 있습니다.

기본 제공 reduce 함수를 사용할 때 입력이 올바르지 않은 경우 builtin_reduce_error 오류가 리턴됩니다. 해당 실패에 대한 자세한 정보는 reason 필드에서 제공됩니다. 오류를 유발한 원래 데이터는 caused_by 필드에서 리턴됩니다.

다음과 같이 응답 예제를 참조하십시오.

{
    "rows": [
        {
            "key": null,
            "value": {
                "error": "builtin_reduce_error",
                "reason": "The _sum function requires that map values be numbers, arrays of numbers, or objects. Objects can't be mixed with other data structures. Objects can be arbitrarily nested, if the values for all fields are themselves numbers, arrays of numbers, or objects.",
                "caused_by": [
                    {
                        "a": 1
                    },
                    {
                        "a": 2
                    },
                    {
                        "a": 3
                    },
                    {
                        "a": 4
                    }
                ]
            }
        }
    ]
}

Map 및 reduce 함수 제한사항

여기에서는 Map 및 reduce 함수 제한사항에 대해 설명합니다.

참조 투명성

map 함수는 참조로 투명해야 합니다. 참조 투명성은 결과를 변경하지 않고 표현식을 동일한 값으로 대체할 수 있음을 의미합니다. 이 경우에는 문서 및 key-value 쌍입니다. 참조 투명성 때문에 IBM Cloudant 뷰는 증분식으로 업데이트될 수 있으며, 마지막 업데이트 이후 델타만 다시 인덱스화합니다.

교환 및 연관 특성

참조 투명성 이외에도 reduce 함수에는 입력에 대한 교환 및 연관 특성이 있어야 합니다. 이러한 특성을 통해 MapReduce 함수에서 자체 출력을 감축하고 동일한 응답을 생성할 수 있습니다. 예를 들면 다음과 같습니다.

f(Key, Values) == f(Key, [ f(Key, Values) ] )

결과적으로 IBM Cloudant는 B-트리 인덱스의 내부 노드에 중간 결과를 저장할 수 있게 됩니다. 이러한 제한사항으로 인해 인덱스가 시스템 전체로 분산되어 조회 시 인덱스를 감축할 수 있습니다.

문서 파티셔닝

분할로 인해 IBM Cloudant는 두 특정 map 함수의 출력이 동일한 reduce 호출 인스턴스로 전달된다는 보장은 없습니다. 순서에 의존해서는 안됩니다. 사용하는 감축 함수는 이에 전달된 모든 값을 고려하고 순서에 관계없이 올바른 응답을 리턴해야 합니다. IBM Cloudant에서는 또한 인덱스를 빌드할 때 수행할 필요가 없는 경우에도 쿼리 시간에 rereduce=true의 사용으로 감축 함수를 호출하도록 보장됩니다. 해당 경우에는 함수가 올바르게 작동하는 것이 중요합니다. (rereduce=true은(는) 키 매개변수가 null이고 값 배열이 이전 감축 함수 호출의 결과로 채워짐을 의미합니다.)

감축된 값 크기

IBM Cloudant에서 보기 인덱스를 계산한 후 해당 감축 값은 각각의 B-트리 노드 포인터 내에서 이러한 값을 캐싱합니다. 이제, IBM Cloudant에서는 B-트리를 업데이트할 때 감축된 값을 재사용할 수 있습니다. reduce 함수에서 리턴되는 데이터의 양에 주의해야 합니다.

리턴되는 데이터 세트의 크기가 작은 상태로 유지되고 log(num_rows_processed)보다 빠르게 확대되지 않는 것이 좋습니다. 이 제한사항을 무시하면 IBM Cloudant에서 자동으로 오류를 발생시키지는 않지만, B-트리 성능이 크게 저하됩니다. 데이터 세트가 작은 상태에서는 보기가 올바르게 작동하지만 데이터가 추가되면 작업이 종료되는 경우 보기에서 성장률 특성 제한사항을 위반한 것일 수도 있습니다.

실행 환경

색인화 기능은 문서가 환경에서 사용되는 메모리의 일부를 구성하는 메모리가 제한된 환경에서 작동합니다. 코드의 스택과 문서는 메모리에 맞아야 합니다. 문서를 최대 크기인 64MB로 제한합니다.

options.partitionedtrue인 경우 JavaScript 감축자가 존재하지 않음

options.partitionedtrue로 설정된 디자인 문서에는 JavaScript reduce 함수를 포함시킬 수 없으며 기본 제공 Erlang 감축자(예: _stats)만 사용할 수 있습니다.

보기 정의 저장

각각의 보기는 JavaScript 함수입니다. 보기는 디자인 문서에 저장됩니다. 따라서, 뷰를 저장하기 위해, IBM Cloudant에서는 단순히 기능 정의를 디자인 문서에 저장합니다. 디자인 문서는 다른 문서와 마찬가지로 작성하거나 업데이트할 수 있습니다.

보기 정의를 저장합니다, PUT 보기 정의 콘텐츠를 _design 문서에 추가합니다.

다음 예제에서 getVerifiedEmails 보기는 map 함수로 정의되어 있으며 디자인 문서의 views 필드에서 사용할 수 있습니다.

PUT 메소드를 사용하여 디자인 문서에 보기를 추가하십시오.

PUT $SERVICE_URL/$DATABASE/_design/$DDOC HTTP/1.1
Content-Type: application/json

다음 샘플은 뷰 정의가 있는 allusers 디자인 문서에 새 getVerifiedEmails 명명된 뷰 함수를 추가하는 예제입니다:

{
    "views": {
        "getVerifiedEmails": {
            "map": "function(user) { if(user.email_verified === true){ emit(doc.email, {name: user.name, email_verified: user.email_verified, joined: user.joined}) }}  "
        }
    }
}

요청 예제를 참조하십시오.

curl -X PUT "$SERVICE_URL/users/_design/allusers" --data '{
  "views": {
    "getVerifiedEmails": {
      "map": "function(user) { if(user.email_verified === true){ emit(doc.email, {name: user.name, email_verified: user.email_verified, joined: user.joined}) }}"
    }
  }
}'
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.DesignDocument;
import com.ibm.cloud.cloudant.v1.model.DesignDocumentViewsMapReduce;
import com.ibm.cloud.cloudant.v1.model.DocumentResult;
import com.ibm.cloud.cloudant.v1.model.PutDesignDocumentOptions;

import java.util.Collections;

Cloudant service = Cloudant.newInstance();

DesignDocumentViewsMapReduce emailViewMapReduce =
    new DesignDocumentViewsMapReduce.Builder()
        .map("function(user) { if(user.email_verified === true){ emit(doc.email,{name: user.name, email_verified: user.email_verified, joined: user.joined}) }")
        .build();

DesignDocument designDocument = new DesignDocument();
designDocument.setViews(
        Collections.singletonMap("getVerifiedEmails", emailViewMapReduce));

PutDesignDocumentOptions designDocumentOptions =
    new PutDesignDocumentOptions.Builder()
        .db("users")
        .designDocument(designDocument)
        .ddoc("allusers")
        .build();

DocumentResult response =
    service.putDesignDocument(designDocumentOptions).execute()
        .getResult();

System.out.println(response);
import { CloudantV1 } from '@ibm-cloud/cloudant';

const service = CloudantV1.newInstance({});

const emailViewMapReduce: CloudantV1.DesignDocumentViewsMapReduce = {
  map: 'function(user) { if(user.email_verified === true){ emit(doc.email, {name: user.name, email_verified: user.email_verified, joined: user.joined}) }}'
}

const designDocument: CloudantV1.DesignDocument = {
  views: {'getVerifiedEmails': emailViewMapReduce}
}

service.putDesignDocument({
  db: 'users',
  designDocument: designDocument,
  ddoc: 'allusers'
}).then(response => {
  console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1

service = CloudantV1.new_instance()

email_view_map_reduce = DesignDocumentViewsMapReduce(
  map='function(user) { if(user.email_verified === true){ emit(doc.email, {name: user.name, email_verified: user.email_verified, joined: user.joined}) }}'
)

design_document = DesignDocument(
  views={'getVerifiedEmails': email_view_map_reduce}
)

response = service.put_design_document(
  db='users',
  design_document=design_document,
  ddoc='allusers'
).get_result()

print(response)
emailViewMapReduce, err := service.NewDesignDocumentViewsMapReduce(
  "function(user) { if(user.email_verified === true){ emit(doc.email, {name: user.name, email_verified: user.email_verified, joined: user.joined}) }}",
)
if err != nil {
  panic(err)
}

designDocument := &cloudantv1.DesignDocument{
  Views: map[string]cloudantv1.DesignDocumentViewsMapReduce{
    "getVerifiedEmails": *emailViewMapReduce,
  },
}

putDesignDocumentOptions := service.NewPutDesignDocumentOptions(
  "users",
  "allusers",
  designDocument,
)

documentResult, _, err := service.PutDesignDocument(putDesignDocumentOptions)
if err != nil {
  panic(err)
}

b, _ := json.MarshalIndent(documentResult, "", "  ")
fmt.Println(string(b))

이전 Go 예제에서는 다음 가져오기 블록이 필요합니다.

import (
  "encoding/json"
  "fmt"
  "github.com/IBM/cloudant-go-sdk/cloudantv1"
)

모든 Go 예제에서는 service 오브젝트가 초기화되어야 합니다. 자세한 정보는 API 문서 인증 섹션 예제를 참조하십시오.