버킷 패턴은 긴 데이터 시리즈를 별개의 객체로 분리합니다. 큰 데이터 시리즈를 작은 그룹으로 분리하면 쿼리 액세스 패턴을 개선하고 애플리케이션 로직을 간소화할 수 있습니다. 버킷팅은 단일 사용자의 주식 거래와 같이 중앙 엔터티와 관련된 유사한 객체가 있을 때 유용합니다.
애플리케이션이 페이지당 표시하는 요소를 기반으로 데이터를 그룹화하여 페이지 매김에 버킷 패턴을 사용할 수 있습니다. 이 접근 방식은 MongoDB의 유연한 데이터 모델을 사용하여 애플리케이션에 필요한 데이터에 따라 데이터를 저장합니다.
팁
시계열 컬렉션 은 버킷 패턴 을 자동으로 적용 하며, Time Series 데이터 를 버킷화하는 대부분의 애플리케이션에 적합합니다.
이 작업에 대하여
주식 거래를 추적하는 다음 스키마를 가정해 보겠습니다. 초기 스키마는 버킷 패턴을 사용하지 않고 각 거래를 개별 문서에 저장합니다.
db.trades.insertMany( [ { "ticker" : "MDB", "customerId": 123, "type" : "buy", "quantity" : 419, "date" : ISODate("2023-10-26T15:47:03.434Z") }, { "ticker" : "MDB", "customerId": 123, "type" : "sell", "quantity" : 29, "date" : ISODate("2023-10-30T09:32:57.765Z") }, { "ticker" : "GOOG", "customerId": 456, "type" : "buy", "quantity" : 50, "date" : ISODate("2023-10-31T11:16:02.120Z") } ] )
이 애플리케이션은 한 번에 한 고객이 수행한 주식 거래를 표시하며 페이지당 10개의 거래를 표시합니다. 애플리케이션 로직을 단순화하려면 버킷 패턴을 사용하여 customerId 별로 10개 그룹으로 거래를 그룹화합니다.
단계
customerId를 기준으로 데이터를 그룹화합니다.
각 customerId에 대해 단일 문서를 갖도록 스키마를 재구성합니다.
{ "customerId": 123, "history": [ { "type": "buy", "ticker": "MDB", "qty": 419, "date": ISODate("2023-10-26T15:47:03.434Z") }, { "type": "sell", "ticker": "MDB", "qty": 29, "date": ISODate("2023-10-30T09:32:57.765Z") } ] }, { "customerId": 456, "history": [ { "type" : "buy", "ticker" : "GOOG", "quantity" : 50, "date" : ISODate("2023-10-31T11:16:02.120Z") } ] }
버킷 패턴을 사용하면 다음이 가능합니다.
일반적인
customerId값을 가진 문서는 단일 문서로 압축되며customerId는 최상위 필드입니다.해당 고객에 대한 거래는
history라는 내장된 배열 필드로 그룹화됩니다.
각 버킷의 식별자와 개수를 추가합니다.
1 db.trades.drop() 2 3 db.trades.insertMany( 4 [ 5 { 6 "_id": "123_1698349623", 7 "customerId": 123, 8 "count": 2, 9 "history": [ 10 { 11 "type": "buy", 12 "ticker": "MDB", 13 "qty": 419, 14 "date": ISODate("2023-10-26T15:47:03.434Z") 15 }, 16 { 17 "type": "sell", 18 "ticker": "MDB", 19 "qty": 29, 20 "date": ISODate("2023-10-30T09:32:57.765Z") 21 } 22 ] 23 }, 24 { 25 "_id": "456_1698765362", 26 "customerId": 456, 27 "count": 1, 28 "history": [ 29 { 30 "type" : "buy", 31 "ticker" : "GOOG", 32 "quantity" : 50, 33 "date" : ISODate("2023-10-31T11:16:02.120Z") 34 } 35 ] 36 }, 37 ] 38 )
_id 필드 값은 customerId와 history 필드의 첫 번째 거래 시간(유닉스 시간 이후)을 초 단위로 연결한 것입니다.
count 필드 는 해당 문서의 history 배열 에 있는 요소의 수를 나타냅니다. count 필드 는 페이지 매김 로직을 구현 하는 데 사용됩니다.
다음 단계
버킷 패턴을 사용하도록 스키마를 업데이트한 후에는 데이터 읽기 및 쓰기를 위한 애플리케이션 로직을 업데이트하세요. 다음 섹션을 참조하세요.
Bucket 패턴으로 데이터 쿼리하기
업데이트된 스키마에서 각 문서에는 애플리케이션의 단일 페이지에 대한 데이터가 포함됩니다. _id 및 count 필드를 사용하여 데이터를 반환하고 업데이트하는 방법을 결정할 수 있습니다.
해당 페이지의 데이터를 쿼리하려면 정규식 쿼리를 사용하여 지정된 customerId에 대한 데이터를 반환하고, skip을(를) 사용하여 올바른 페이지에 대한 데이터로 반환합니다. _id에 대한 정규식 쿼리는 default _id index를 사용하므로 추가 인덱스 없이도 성능이 우수한 쿼리를 생성합니다.
다음 쿼리는 고객 123의 첫 번째 거래 페이지에 대한 데이터를 반환합니다.
db.trades.find( { "_id": /^123_/ } ).sort( { _id: 1 } ).limit(1)
이후 페이지에 대한 데이터를 반환하려면 데이터를 표시하려는 페이지보다 1이 적은 skip 값을 지정합니다. 예를 들어 10페이지에 대한 데이터를 표시하려면 다음 쿼리를 실행합니다.
db.trades.find( { "_id": /^123_/ } ).sort( { _id: 1 } ).skip(9).limit(1)
참고
샘플 데이터에 첫 페이지에 대한 문서만 포함되어 있기 때문에 이전의 쿼리는 결과가 반환되지 않습니다.
버킷 패턴으로 데이터 삽입하기
이제 스키마가 버킷 패턴을 사용하므로 애플리케이션 로직을 업데이트하여 새 거래를 올바른 버킷에 삽입합니다. 적절한 customerId 및 버킷을 사용해 거래를 버킷에 삽입하려면 업데이트 명령을 사용합니다.
다음 명령은 customerId: 123에 대한 새로운 거래를 삽입합니다.
db.trades.updateOne( { "_id": /^123_/, "count": { $lt: 10 } }, { "$push": { "history": { "type": "buy", "ticker": "MSFT", "qty": 42, "date": ISODate("2023-11-02T11:43:10") } }, "$inc": { "count": 1 }, "$setOnInsert": { "_id": "123_1698939791", "customerId": 123 } }, { upsert: true } )
애플리케이션 은 페이지당 10 개의 거래를 표시합니다. 업데이트 필터하다 는 count 가 10 보다 작은 customerId: 123 에 대한 문서 를 검색하며, 이는 버킷에 전체 데이터 페이지가 포함되어 있지 않음을 의미합니다.
"_id": /^123_/와 일치하는 문서 가 있고 해당 문서의count이 10 보다 작은 경우, 업데이트 명령은 새 거래를 일치하는 문서의history배열 로 푸시합니다.일치하는 문서 가 없는 경우 업데이트 명령은 새 거래로 새 문서 를 삽입합니다(
upsert이true이므로). 새 문서 의_id필드 는customerId와 거래의 유닉스 시간 시간 이후의 시간(초)을 연결한 것입니다.
업데이트 명령 로직은 history 배열에 10개 이상의 문서가 포함되지 않도록 하여 무제한 배열을 방지합니다.
업데이트 작업을 실행하면 trades 컬렉션에 다음 문서가 포함됩니다.
[ { _id: '123_1698349623', customerId: 123, count: 3, history: [ { type: 'buy', ticker: 'MDB', qty: 419, date: ISODate("2023-10-26T15:47:03.434Z") }, { type: 'sell', ticker: 'MDB', qty: 29, date: ISODate("2023-10-30T09:32:57.765Z") }, { type: 'buy', ticker: 'MSFT', qty: 42, date: ISODate("2023-11-02T11:43:10.000Z") } ] }, { _id: '456_1698765362', customerId: 456, count: 1, history: [ { type: 'buy', ticker: 'GOOG', quantity: 50, date: ISODate("2023-10-31T11:16:02.120Z") } ] } ]
결과
버킷 패턴 을 구현 한 후에는 애플리케이션 에 결과를 반환하기 위해 페이지 매김 로직을 통합할 필요가 없습니다. 데이터가 저장되는 방식은 애플리케이션 에서 데이터가 사용되는 방식과 일치합니다.