1.集計操作
集計操作はデータ レコードを処理し、計算結果を返します。
集計操作では、複数のドキュメントの値をグループ化し、グループ化されたデータに対してさまざまな操作を実行して 1 つの結果を返します。
集計操作には、シングルアクション集計、集計パイプライン、MapReduce の 3 種類があります。
シングルアクション集計: 一般的な集計手順、つまり単一のコレクションからすべてのドキュメントを集計する操作に簡単にアクセスできます。
集約パイプラインはデータ集約のためのフレームワークであり、モデルはデータ処理パイプラインの概念に基づいています。
ドキュメントは、ドキュメントを集計結果に変換する多段階パイプラインに入ります。
MapReduce 操作には 2 つのフェーズがあります。各ドキュメントを処理して入力ドキュメントごとに 1 つ以上のオブジェクトを出力するマップ フェーズと、マップ操作の出力を結合するリデュース フェーズです。
1.単作用重合
MongoDB は、db.collection.estimatedDocumentCount()、db.collection.count()、db.collection.distinct() などのシングルアクション集計関数を提供します。これらの操作はすべて、単一のコレクションからデータを集約します。
書類。これらの操作により、一般的な集計プロセスに簡単にアクセスできますが、集計パイプラインや MapReduce の柔軟性や能力が欠けています。
db.collection.estimatedDocumentCou
nt()
|
コレクションまたはビュー内のすべてのドキュメントの数を返します。
|
db.collection.count()
|
コレクションまたはビューの find() クエリに一致するドキュメントの数を返します。に相当
db.collection.find(query).count() の構築
|
db.collection.distinct()
|
単一のコレクションまたはビュー、および配列内の指定されたフィールドの個別の値を検索します
結果を返します。
|
#检索books集合中所有文档的计数
db.books.estimatedDocumentCount()
#计算与查询匹配的所有文档
db.books.count({favCount:{$gt:50}})
#返回不同type的数组
db.books.distinct("type")
#返回收藏数大于90的文档不同type的数组
db.books.distinct("type",{favCount:{$gt:90}})
注: シャードクラスターでは、孤立したドキュメントがある場合、またはチャンクの移行が進行中の場合、db.collection.count()
クエリ述部が存在しないと、カウントが不正確になる可能性があります。これらの状況を回避するには、シャードクラスターで次を使用します。
db.collection.aggregate()方法。
2.重合パイプライン
MongoDB 集約フレームワークとは
MongoDB Aggregation Framework (Aggregation Framework) は、 1 つまたは複数のコレクションに作用する
こと
、コレクション内のデータに対して一連の操作を実行すること、これらのデータを目的の形式に変換すること、およびこれらのデータを目的の形式に変換することを実行できるコンピューティング フレームワークです。
効果の点では、集計フレームワークは SQL クエリの GROUP BY、LEFT OUTER JOIN、AS などと同等です。
パイプライン (Pipeline) とステージ (
Stage)
集計演算プロセス全体はパイプライン (Pipeline) と呼ばれ、複数のステージ (
ステージ)
、各パイプライン: 一連のドキュメント (生データ) を受け取ります。各ステージはこれらのドキュメントに対して一連の操作を実行します。結果のドキュメントは次のステージに出力されます。
集約パイプライン操作の構文
pipeline = [$stage1, $stage2, ...$stageN];
db.collection.aggregate(pipeline, {options})
パイプライン データ集約ステージのセット。$out、$Merge、$geonear ステージを除き、各ステージはパイプライン内で複数回出現できます。
options オプションの集計操作のその他のパラメータ。含まれるもの: クエリ プラン、一時ファイル、カーソル、最大操作時間、読み取りおよび書き込み戦略、必須インデックスなどを使用するかどうか。
一般的なパイプライン集約ステージ
集約パイプラインには非常に豊富な集約ステージが含まれています。最も一般的に使用される集約ステージは次のとおりです。
データの準備
データセットを準備してスクリプトを実行する
var tags = ["nosql","mongodb","document","developer","popular"];
var types = ["technology","sociality","travel","novel","literature"];
var books=[];
for(var i=0;i<50;i++){
var typeIdx = Math.floor(Math.random()*types.length);
var tagIdx = Math.floor(Math.random()*tags.length);
var tagIdx2 = Math.floor(Math.random()*tags.length);
var favCount = Math.floor(Math.random()*100);
var username = "xx00"+Math.floor(Math.random()*10);
var age = 20 + Math.floor(Math.random()*15);
var book = {
title: "book‐"+i,
type: types[typeIdx],
tag: [tags[tagIdx],tags[tagIdx2]],
favCount: favCount,
author: {name:username,age:age}
};
books.push(book)
}
db.books.insertMany(books);
$プロジェクト
射影操作
。元のフィールドを指定された名前に射影します。たとえば、コレクション内のタイトルを名前に射影します。
db.books.aggregate([{$project:{name:"$title"}}])
$project は
出力ドキュメントの形式を柔軟に制御でき
、不要なフィールドを削除することもできます
db.books.aggregate([{$project:{name:"$title",_id:0,type:1,author:1}}])
ネストされたドキュメントからフィールドを除外する
db.books.aggregate([
{$project:{name:"$title",_id:0,type:1,"author.name":1}}
])
或者
db.books.aggregate([
{$project:{name:"$title",_id:0,type:1,author:{name:1}}}
])
$match
$match はドキュメントをフィルタリングするために使用され
、取得されたドキュメントのサブセットに集約できます。$match は使用できます。
地理空間を除くすべての通常のクエリ演算子を使用し、
実際のアプリケーションではできる限り $match をパイプラインの先頭に置きます。
顔の位置
も これには 2 つの利点があります。1 つは、不要なドキュメントをすぐにフィルタリングしてパイプラインの作業負荷を軽減できることです。2 つは
はい、$match が射影とグループ化の前に実行される場合、クエリでインデックスを使用できます。
db.books.aggregate([{$match:{type:"technology"}}])
スクリーニング パイプライン オペレーションが他のパイプライン オペレーションと連携する場合は、それを初期段階に置くようにしてください。これにより、後続のパイプラインが削減される可能性があります。
効率を向上させるためにオペレーターが操作する文書の数
db.books.aggregate([
{$match:{type:"technology"}},
{$project:{name:"$title",_id:0,type:1,author:{name:1}}}
])
$count
クエリに一致する結果の数を数えて返します。
db.books.aggregate([
{$match:{type:"technology"}},
{$count: "type_count"}
])
$match ステージでは、タイプがテクノロジーと一致するドキュメントをフィルターで除外し、次のステージに渡します。
$count
ステージは、集計パイプラインに残っているドキュメントの数を返し、この値を type_count に割り当てます。
$グループ
指定された式によってドキュメントをグループ化し、個別にグループ化された各ドキュメントを次のステージに出力します
。出力ドキュメントパッケージ
キーごとにさまざまなグループを含む _id フィールドが含まれます。
出力ドキュメントには、$group の _id フィールドによってグループ化されたいくつかのアキュムレータ テーブルを保持する計算フィールドを含めることもできます。
式の値。
$group は特定のドキュメントを出力せず、統計だけを出力します。
{ $group: { _id: <expression>, <field1>: { <accumulator1> : <expression1>
}, ... } }
1. _id フィールドは必須ですが、入力ドキュメント全体の累積値を計算するには、_id に null 値を指定できます。
2. 残りの計算フィールドはオプションであり、<accumulator> 演算子を使用して計算されます。
3. _id および <accumulator> 式は、任意の有効な
式を受け入れることができます
。
アキュムレータ演算子
名前
|
説明 | 類推SQL |
平均$
|
平均値を計算する
|
平均
|
$first
|
利用可能な場合はソートされた各セットの最初のドキュメントを返し、そうでない場合はデフォルトの保存順序で最初のドキュメントを返します。
|
制限0,1
|
$last
|
ソートされている場合は各グループの最後のドキュメントを返し、デフォルトの保存順序の最後のドキュメントではない場合はソートされて返します。
|
|
$max
|
グループ化に従って、コレクション内のすべてのドキュメントに対応する最大値を取得します
|
最大
|
$分
|
グループ化に従って、コレクション内のすべてのドキュメントに対応する最小値を取得します。
|
分
|
$pus
|
指定された式の値を配列に追加します
|
|
$addToSet
|
式の値をコレクションに追加します (重複なし、順序なし)
|
|
$sum
|
合計を計算する
|
和
|
$stdDevPop
|
入力値の母標準偏差を返します。
|
|
$stdDevSamp
|
入力値のサンプル標準偏差を返します。
|
$group ステージのメモリ制限は 100M です。デフォルトでは、ステージがこの制限を超えると、$group はエラーを生成します。
エラー。
ただし、大規模なデータセットの処理を許可するには、allowDiskUse オプションを true に設定して、$group 操作を有効にします。
一時ファイルに書き込みます。
蔵書数・総蔵数・平均
db.books.aggregate([
{$group:{_id:null,count:{$sum:1},pop:{$sum:"$favCount"},avg:{$avg:"$favCount"}}}
])
著者ごとに蔵書の総数を数える
db.books.aggregate([
{$group:{_id:"$author.name",pop:{$sum:"$favCount"}}}
])
各著者ごとに各本のお気に入りの数を数えます
db.books.aggregate([
{$group:{_id:{name:"$author.name",title:"$title"},pop:{$sum:"$favCount"}}}
])
各著者の本の活字集
db.books.aggregate([
{$group:{_id:"$author.name",types:{$addToSet:"$type"}}}
])
$unwind
配列は個別のドキュメントに分割できます
{
$unwind:
{
#要指定字段路径,在字段名称前加上$符并用引号括起来。
path: <field path>,
#可选,一个新字段的名称用于存放元素的数组索引。该名称不能以$开头。
includeArrayIndex: <string>,
#可选,default :false,若为true,如果路径为空,缺少或为空数组,则$unwind输出文档
preserveNullAndEmptyArrays: <boolean>
} }
xx006 という名前の著者の本のタグ配列が複数のドキュメントに分割されています
db.books.aggregate([
{$match:{"author.name":"xx006"}},
{$unwind:"$tag"}
])
db.books.aggregate([
{$match:{"author.name":"xx006"}}
])
各著者の本のタグを集めたものです。
db.books.aggregate([
{$unwind:"$tag"},
{$group:{_id:"$author.name",types:{$addToSet:"$tag"}}}
])
$limit
db.books.aggregate([
{$limit : 5 }
])
この操作では、パイプされた最初の 5 つのドキュメントのみが返されます。$limit は、渡されるドキュメントの内容には影響しません。
注: $sort がパイプラインの $limit の直前に発生する場合、$sort 操作はプロセス内の最初の n ノットのみを維持します。
ここで、
n は指定された制限であり、MongoDB は n 個の項目をメモリに保存するだけで済みます。
$スキップ
ステージに入る指定された数のドキュメントをスキップし、残りをパイプラインの次のステージに渡します。
db.books.aggregate([
{$skip : 5 }
])
このアクションでは、パイプラインによって渡される最初の 5 つのドキュメントがスキップされます。$skip は、パイプラインに沿って渡されるドキュメントの内容には影響しません。
$sort
すべての入力ドキュメントを並べ替えて、並べ替えられた順序でパイプラインに返します。
文法:
{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }
フィールドを並べ替えるには、次の例に示すように、並べ替え順序を 1 または -1 に設定してそれぞれ昇順または降順を指定します。
見せる:
db.books.aggregate([
{$sort : {favCount:‐1,title:1}}
])
$lookup
Mongodb 3.2 バージョンの新機能で、主に複数テーブル関連付けクエリを実装するために使用されます。これは、リレーショナル データベースの複数テーブル関連付けクエリと同等です。
問い合わせてください。
処理される各入力ドキュメントは $lookup ステージによって処理され、出力される新しいドキュメントには新しいドキュメントが含まれます。
結果の配列
(必要に応じて新しいキーに名前を付けることができます)。配列列に格納されるデータは、コレクションに結合されるアダプター ドキュメントからのものです。
そうでない場合、コレクションは空です (つまり [ ])
文法:
db.collection.aggregate([{
$lookup: {
from: "<collection to join>",
localField: "<field from the input documents>",
foreignField: "<field from the documents of the from collection>",
as: "<output array field>"
}
})
から
|
同じデータベースに参加するのを待っているコレクション。
|
ローカルフィールド
|
ソース コレクション内の一致値の場合、入力コレクション内のドキュメントに localField のキー (フィールド) がない場合、処理中にドキュメントにはデフォルトで localField: null キーと値のペアが含まれます。
|
外国人フィールド
|
結合されるコレクションの一致値。結合されるコレクション内のドキュメントにForeignField値がない場合、処理中にドキュメントにはデフォルトでforeignField: nullのキーと値のペアが含まれます。
|
として
|
出力ドキュメントに追加される新しい値に名前を付けます。値が入力コレクションにすでに存在する場合、その値は上書きされます。
|
注: null = null これは true
その構文関数は次の疑似 SQL ステートメントに似ています。
SELECT *, <output array field>
FROM collection
WHERE <output array field> IN (SELECT *
FROM <collection to join>
WHERE <foreignField>= <collection.localField>);
ケース
データの準備
db.customer.insert({customerCode:1,name:"customer1",phone:"13112345678",address:"test1"})
db.customer.insert({customerCode:2,name:"customer2",phone:"13112345679",address:"test2"})
db.order.insert({orderId:1,orderCode:"order001",customerCode:1,price:200})
db.order.insert({orderId:2,orderCode:"order002",customerCode:2,price:400})
db.orderItem.insert({itemId:1,productName:"apples",qutity:2,orderId:1})
db.orderItem.insert({itemId:2,productName:"oranges",qutity:2,orderId:1})
db.orderItem.insert({itemId:3,productName:"mangoes",qutity:2,orderId:1})
db.orderItem.insert({itemId:4,productName:"apples",qutity:2,orderId:2})
db.orderItem.insert({itemId:5,productName:"oranges",qutity:2,orderId:2})
db.orderItem.insert({itemId:6,productName:"mangoes",qutity:2,orderId:2})
アソシエーションクエリ
db.customer.aggregate([
{$lookup: {
from: "order",
localField: "customerId",
foreignField: "customerId",
as: "customerOrder"
}
}
])
db.order.aggregate([
{$lookup: {
from: "customer",
localField: "customerCode",
foreignField: "customerCode",
as: "curstomer"
}
},
{$lookup: {
from: "orderItem",
localField: "orderId",
foreignField: "orderId",
as: "orderItem"
}
} ])
集計操作ケース1
各カテゴリの書籍ドキュメントの数を数える
db.books.aggregate([
{$group:{_id:"$type",total:{$sum:1}}},
{$sort:{total:‐1}}
])
タグの人気ランキング。タグの人気は、関連付けられた書籍ドキュメントの
お気に入り数 ( favCount ) に基づいて計算されます。
db.books.aggregate([
{$match:{favCount:{$gt:0}}},
{$unwind:"$tag"},
{$group:{_id:"$tag",total:{$sum:"$favCount"}}},
{$sort:{total:‐1}}
])
1. $match ステージ: favCount=0 でドキュメントをフィルタリングするために使用されます。
2. $unwind ステージ: タグ配列を展開するために使用され、3 つのタグを含むドキュメントが 3 つの項目に分解されます。
3. $group ステージ: 逆アセンブルされたドキュメントをグループ化して計算します。$sum: "$favCount" は、favCount フィールドに従って累積することを意味します。
4. $sort ステージ: グループ計算の出力を受け取り、合計スコアで並べ替えます。
書籍文書コレクションの数を数える[0,10),[10,60),[60,80),[80,100),[100,+∞]
db.books.aggregate([{
$bucket:{
groupBy:"$favCount",
boundaries:[0,10,60,80,100],
default:"other",
output:{"count":{$sum:1}}
}
}])
二、MapReduce
MapReduce 操作は、大量のデータ処理作業を複数のスレッドに分割して並列処理し、結果を 1 つにマージします。
上昇。MongoDB が提供する Map-Reduce は非常に柔軟で、大規模なデータ分析に実用的です。
MapReduce には 2 つのフェーズがあります。
1. 同一Keyの文書データを統合するマップステージ
2. 統計出力の縮小段階でマップ操作の結果を結合します。
MongoDB 5.0 では、map-reduce 操作は非推奨になりました。
集約パイプラインはさらに多くの機能を提供します
性能も使いやすさも良好。Map-Reduce 操作は、$group などの集約パイプライン演算子を使用して書き換えることができます。
$mergeなど