MongoDB のクエリ - Web SDK
項目一覧
- 前提条件
- プロジェクトを設定する
- プロジェクトを設定する
- MongoDB Atlas Service クラスターのリンク
- Realm 依存関係のインポート
- MongoDB コレクション ハンドルのインスタンス化
- サンプルデータ
- ドキュメントの作成
- 単一ドキュメントのインサート
- 複数のドキュメントの挿入
- ドキュメントを読む
- 単一ドキュメントの検索
- 複数ドキュメントの検索
- コレクション内のドキュメントをカウント
- Update Documents
- 単一ドキュメントの更新
- 複数のドキュメントの更新
- ドキュメントをアップサートする
- Delete Documents
- 単一ドキュメントの削除
- 複数のドキュメントの削除
- 変更の監視
- コレクションの変更の監視
- フィルターでコレクションの変更を監視
- ドキュメントの集計
- コレクション内のドキュメントの集計
- 集計ステージ
- フィルター ドキュメント
- グループ ドキュメント
- ドキュメントのページ分割
- プロジェクト ドキュメント フィールド
- ドキュメントへのフィールドの追加
- Unwind Array Values
Realm Web SDK の MongoDB クライアントとQuery APIを併用すると、MongoDB Atlas に保存されているデータをクライアント アプリケーションのコードから直接クエリできます。 Atlas App Servicesは、ログインしたユーザーまたは各ドキュメントの内容に基づいて結果を安全に取得するためのコレクションにデータ アクセスルールを提供します。
次のアクションにより、Realm Web SDK を使用して、Web アプリからリンクされた MongoDB Atlas クラスターをクエリできます。
注意
このページで説明されている各操作では、クエリを使用して、操作が実行されるコレクション内の特定のドキュメントを照合します。 フィルターがコレクション内の複数のドキュメントに一致する場合、ソートパラメーターを指定しない限り、ドキュメントは不特定の順序で返されます。 つまり、 findOne()
、 updateOne()
、またはdeleteOne()
関数のいずれかに並べ替えを指定しないと、操作はクエリに一致する任意のドキュメントと一致する可能性があります。 ソートについて詳しくは、 cursor.sort() を参照してください。
前提条件
Web アプリケーションから MongoDB をクエリする前に、App Services App で MongoDB Data Access を設定する必要があります。 バックエンド アプリを設定して Realm SDK クエリ Atlas を使用できるようにする方法については、App Services ドキュメントの「 MongoDB データアクセスの設定 」を参照してください。
プロジェクトを設定する
プロジェクトを設定する
「 Web 用の Realm のインストール 」ガイドの手順に従います。
MongoDB Atlas Service クラスターのリンク
「データソースのリンク 」ガイドの手順に従います。 サービスに意味のある名前を割り当てます。この名前は、Realm SDK を使用してクラスターに接続するために必要になります。
サンプルデータ
このページの例では、植物店のチェーンで販売されるさまざまな植物を説明する次の MongoDB コレクションを使用します。
{ _id: ObjectId("5f87976b7b800b285345a8b4"), name: "venus flytrap", sunlight: "full", color: "white", type: "perennial", _partition: "Store 42", }, { _id: ObjectId("5f87976b7b800b285345a8b5"), name: "sweet basil", sunlight: "partial", color: "green", type: "annual", _partition: "Store 42", }, { _id: ObjectId("5f87976b7b800b285345a8b6"), name: "thai basil", sunlight: "partial", color: "green", type: "perennial", _partition: "Store 42", }, { _id: ObjectId("5f87976b7b800b285345a8b7"), name: "helianthus", sunlight: "full", color: "yellow", type: "annual", _partition: "Store 42", }, { _id: ObjectId("5f87976b7b800b285345a8b8"), name: "petunia", sunlight: "full", color: "purple", type: "annual", _partition: "Store 47", },
ドキュメントの作成
これらのコード スニペットは、 WebアプリからMongoDBコレクションに 1 つ以上のドキュメントを挿入する方法を示しています。挿入操作は、 MongoDBに追加するドキュメントを引数として受け取り、 Promise を返します は、操作の実行の結果を含むオブジェクトに解決されます。
単一ドキュメントのインサート
collection.insertOne() を呼び出すことで、単一のドキュメントを挿入できます。
次のスニペットは、「 Ops Manager 」の植物を説明する単一のドキュメントを、店舗のグループで販売するプランを説明するドキュメントのコレクションに挿入します。
const result = await plants.insertOne({ name: "lily of the valley", sunlight: "full", color: "white", type: "perennial", _partition: "Store 47", }); console.log(result);
このスニペットを実行すると、次のような出力が生成されます。
{ insertedId: ObjectId("5f879f83fc9013565c23360e") }
複数のドキュメントの挿入
collection.insertMany() を使用して、複数のドキュメントを同時に挿入できます。
次のスニペットは、プランを説明する 3 つのドキュメントを、店舗のグループで販売するプランを説明するドキュメントのコレクションに挿入します。
const result = await plants.insertMany([ { name: "rhubarb", sunlight: "full", color: "red", type: "perennial", _partition: "Store 47", }, { name: "wisteria lilac", sunlight: "partial", color: "purple", type: "perennial", _partition: "Store 42", }, { name: "daffodil", sunlight: "full", color: "yellow", type: "perennial", _partition: "Store 42", }, ]); console.log(result);
このスニペットを実行すると、次のような出力が生成されます。
{ insertedIds: [ ObjectId("5f87a0defc9013565c233611"), ObjectId("5f87a0defc9013565c233612"), ObjectId("5f87a0defc9013565c233613"), ], }
ドキュメントを読む
これらのコード スニペットは、モバイル アプリケーションから MongoDB コレクションに保存されているデータを読み取る方法を示しています。 読み取り操作では、クエリフィルターを使用して、データベースから返されるドキュメントを指定します。 読み取り操作は Promise を返します は、次のいずれかに解決されます。単一の一致したドキュメント(findOne()
の場合)、数値( の場合)、一致したドキュメントの配列(count()
find()
の場合)。
単一ドキュメントの検索
collection.findOne() を使用して単一のドキュメントを検索できます。
const venusFlytrap = await plants.findOne({ name: "venus flytrap" }); console.log("venusFlytrap", venusFlytrap);
このスニペットを実行すると、次のような出力が生成されます。
{ _id: ObjectId("5f87976b7b800b285345a8b4"), name: "venus flytrap", sunlight: "full", color: "white", type: "perennial", _partition: "Store 42", }
複数ドキュメントの検索
collection.find() を使用して複数のドキュメントを見つけることができます。
次のスニペットは、値が「 type
」という名前のフィールドを含む店舗のグループに販売されているプランを説明するドキュメントのコレクション内のすべてのドキュメントを検索します。
const perennials = await plants.find({ type: "perennial" }); console.log("perennials", perennials);
このスニペットを実行すると、次のような出力が生成されます。
[ { _id: ObjectId("5f87976b7b800b285345a8b4"), name: "venus flytrap", sunlight: "full", color: "white", type: "perennial", _partition: "Store 42", }, { _id: ObjectId("5f87976b7b800b285345a8b6"), name: "thai basil", sunlight: "partial", color: "green", type: "perennial", _partition: "Store 42", }, ]
コレクション内のドキュメントをカウント
collection.count()を使用してコレクション内のドキュメントをカウントできます。 どのドキュメントをカウントするかを決定するために、任意のクエリを指定できます。 クエリを指定しない場合、アクションはコレクション内のすべてのドキュメントをカウントします。
次のスニペットは、店舗のグループで販売されるプランを説明するドキュメントのコレクション内のドキュメントの数をカウントします。
const numPlants = await plants.count(); console.log(`There are ${numPlants} plants in the collection`);
このスニペットを実行すると、次のような出力が生成されます。
"There are 5 plants in the collection"
Update Documents
これらのコード スニペットは、モバイル アプリケーションから MongoDB コレクションに保存されているデータをアップデートする方法を示しています。 更新操作では、クエリを使用して更新するドキュメントを指定し、更新演算子を使用してクエリに一致するドキュメントをミューテーションする方法を記述します。 更新操作は Promise を返します は、操作の実行結果を含むオブジェクトに解決されます。
単一ドキュメントの更新
collection.updateOne() を使用して単一のドキュメントを更新できます。
次のスニペットは、 店舗 のグループで販売されるプランを説明するドキュメントのコレクション内の 1 つのドキュメントを更新します。 この操作は、 name
フィールドに値「ペナルティ」が含まれているドキュメントをクエリし、最初に一致したドキュメントのsunlight
フィールドの値を「部分的」に変更します。
const result = await plants.updateOne( { name: "petunia" }, { $set: { sunlight: "partial" } } ); console.log(result);
このスニペットを実行すると、次のような出力が生成されます。
{ matchedCount: 1, modifiedCount: 1 }
複数のドキュメントの更新
collection.updateMany() を使用して単一のドキュメントを更新できます。
次のスニペットは、 店舗 のグループで販売されるプランを説明するドキュメントのコレクション内の複数のドキュメントを更新します。 この操作は、 _partition
フィールドに値「 42が含まれているドキュメントをクエリし、一致する各ドキュメントの_partition
フィールドの値を「 51を保存」に変更します。
const result = await plants.updateMany( { _partition: "Store 42" }, { $set: { _partition: "Store 51" } } ); console.log(result);
このスニペットを実行すると、次のような出力が生成されます。
{ matchedCount: 4, modifiedCount: 4 }
ドキュメントをアップサートする
アップデート操作がコレクション内のどのドキュメントにも一致しない場合は、 upsert
オプションをtrue
に設定することで、アップデート クエリに一致する新しいドキュメントを 1 つ自動的に挿入できます。
次のスニペットは、店舗のグループで販売されているプランを説明するドキュメントのコレクション内のドキュメントを更新するか、クエリに一致するドキュメントがない場合は新しいドキュメントを挿入します。 この操作は、次のドキュメントをクエリします。
sunlight
フィールドの値は「Full」type
フィールドの値は「perennial」color
フィールドの値は「green」_partition
フィールドの値が「Store 47」である
このスニペットはupsert
オプションをtrue
に設定しているため、クエリに一致するドキュメントがない場合、MongoDB はクエリと指定された更新の両方を含む新しいドキュメントを作成します。
const result = await plants.updateOne( { sunlight: "full", type: "perennial", color: "green", _partition: "Store 47", }, { $set: { name: "super sweet basil" } }, { upsert: true } ); console.log(result);
このスニペットを実行すると、次のような出力が生成されます。
{ matchedCount: 0, modifiedCount: 0, upsertedId: ObjectId("5f1f63055512f2cb67f460a3"), }
Delete Documents
これらのコード スニペットは、MongoDB コレクションに保存されているドキュメントをモバイル アプリケーションから削除する方法を示しています。 削除操作では、クエリを使用して削除するドキュメントを指定し、 Promise を返す は、操作の実行結果を含むオブジェクトに解決されます。
単一ドキュメントの削除
collection.deleteOne() を使用して、コレクションから 1 つのドキュメントを削除できます。
次のスニペットは、 店舗のグループで販売されるプランを説明するドキュメントのコレクション内の 1 つのドキュメントを削除します。 この操作は、 color
フィールドの値が「green」であるドキュメントをクエリし、クエリに一致する最初のドキュメントを削除します。
const result = await plants.deleteOne({ color: "green" }); console.log(result);
このスニペットを実行すると、次のような出力が生成されます。
{ deletedCount: 1 }
複数のドキュメントの削除
collection.deleteMany() を使用して、コレクションから複数の項目を削除できます。
次のスニペットは、店舗のグループで販売されるプランを説明するドキュメントのコレクション内の " Store 42にあるプラン照のすべてのドキュメントを削除します。
const result = await plants.deleteMany({ _partition: "Store 42", }); console.log(result);
このスニペットを実行すると、次のような出力が生成されます。
{ deletedCount: 4 }
変更の監視
collection.watch()を呼び出して、コレクション内のドキュメントが追加、変更、または削除されるたびに、リアルタイム通知イベントをサブスクライブできます。 各通知では、変更されたドキュメントとその変更方法、およびイベントの原因となった操作後の完全なドキュメントを指定します。
重要
サーバーレスの制限事項
データソースが Atlas サーバーレスインスタンスの場合、変更を監視することはできません。 MongoDB サーバーレスは現在、変更をリッスンするために監視対象コレクションで使用される 変更ストリーム をサポートしていません。
Atlas App Services は、監視対象のコレクションの MongoDB変更ストリームを使用して変更をリッスンし、サブスクライブしたクライアント アプリケーションに通知をブロードキャストします。 これは、ユーザーがオンラインである間にイベントがいつ発生したかを知りたい場合に役立ちます。 例:
配達場所の追跡
ゲームの最新のスコアと統計情報を取得する
ユーザーが新しいメッセージを送信したときにチャット スレッドを更新する
注意
collection.watch()
は 非同期ジェネレーター を返します により、操作の 変更イベント が発生したときに非同期にプルできます。
コレクションの変更の監視
コレクション内のすべての変更を監視するには、 collection.watch()を呼び出します 引数がない場合は次のようになります。
for await (const change of plants.watch()) { let breakAsyncIterator = false; // Later used to exit async iterator switch (change.operationType) { case "insert": { const { documentKey, fullDocument } = change; console.log(`new document: ${documentKey}`, fullDocument); breakAsyncIterator = true; break; } case "update": { const { documentKey, fullDocument } = change; console.log(`updated document: ${documentKey}`, fullDocument); breakAsyncIterator = true; break; } case "replace": { const { documentKey, fullDocument } = change; console.log(`replaced document: ${documentKey}`, fullDocument); breakAsyncIterator = true; break; } case "delete": { const { documentKey } = change; console.log(`deleted document: ${documentKey}`); breakAsyncIterator = true; break; } } if (breakAsyncIterator) break; // Exit async iterator }
フィルターでコレクションの変更を監視
コレクション内の特定の変更を監視するには、監視する変更イベント値を指定するクエリを使用してcollection.watch()を呼び出します。
for await (const change of plants.watch({ filter: { operationType: "update", "fullDocument.type": "perennial", }, })) { // The change event will always represent a newly inserted perennial const { documentKey, fullDocument } = change; console.log(`new document: ${documentKey}`, fullDocument); break; // Exit async iterator }
ドキュメントの集計
集計操作は、集計パイプラインと呼ばれる一連のステージを通じてコレクション内のすべてのドキュメントを実行します。 集計を使用すると、ドキュメントのフィルタリングと変換、関連するドキュメントのグループに関するサマリー データの収集、その他の複雑なデータ操作が可能になります。
集計操作は集計ステージのリストを入力として受け入れ、 Promise を返します パイプラインによって処理されたドキュメントのコレクションに解決されます。
コレクション内のドキュメントの集計
collection.aggregate() を使用して集計パイプラインを実行できます。
次のスニペットは、 plants
コレクション内のすべてのドキュメントをtype
値でグループ化し、各タイプの数を集計します。
const result = await plants.aggregate([ { $group: { _id: "$type", total: { $sum: 1 }, }, }, { $sort: { _id: 1 } }, ]); console.log(result);
このスニペットを実行すると、次のような出力が生成されます。
[ { _id: "annual", total: 3 }, { _id: "perennial", total: 2 }, ]
集計ステージ
フィルター ドキュメント
$matchステージを使用して、標準の MongoDBクエリ構文に従ってドキュメントをフィルタリングできます。
{ "$match": { "<Field Name>": <Query Expression>, ... } }
例
次の$match
ステージでは、ドキュメントをフィルタリングして、 type
フィールドの値が「perennial」と等しいドキュメントのみを含めます。
const perennials = await plants.aggregate([ { $match: { type: { $eq: "perennial" } } }, ]); console.log(perennials);
[ { "_id": ObjectId("5f87976b7b800b285345a8c4"), "_partition": "Store 42", "color": "white", "name": "venus flytrap", "sunlight": "full", "type": "perennial" }, { "_id": ObjectId("5f87976b7b800b285345a8c6"), "_partition": "Store 42", "color": "green", "name": "thai basil", "sunlight": "partial", "type": "perennial" }, { "_id": ObjectId("5f87a0dffc9013565c233612"), "_partition": "Store 42", "color": "purple", "name": "wisteria lilac", "sunlight": "partial", "type": "perennial" }, { "_id": ObjectId("5f87a0dffc9013565c233613"), "_partition": "Store 42", "color": "yellow", "name": "daffodil", "sunlight": "full", "type": "perennial" }, { "_id": ObjectId("5f1f63055512f2cb67f460a3"), "_partition": "Store 47", "color": "green", "name": "sweet basil", "sunlight": "full", "type": "perennial" } ]
グループ ドキュメント
$groupステージを使用して、1 つ以上のドキュメントのサマリーデータを集計できます。 MongoDB は、 $group
ステージの_id
フィールドに定義された式に基づいてドキュメントをグループ化します。 フィールド名の前に$
を付けることで、特定のドキュメント フィールドを参照できます。
{ "$group": { "_id": <Group By Expression>, "<Field Name>": <Aggregation Expression>, ... } }
例
次の$group
ステージでは、ドキュメントをtype
type
フィールドの値で配置し、一意の 各 値が表示される植物ドキュメントの数を計算します。
const result = await plants.aggregate([ { $group: { _id: "$type", numItems: { $sum: 1 }, }, }, { $sort: { _id: 1 } }, ]); console.log(result);
[ { _id: "annual", numItems: 1 }, { _id: "perennial", numItems: 5 }, ]
ドキュメントのページ分割
結果をページ分割するには、 $match
、 $sort
、 $limit
演算子を使用した範囲集計クエリを使用できます。 ドキュメントのページ分割の詳細については、 ドキュメントの「 範囲クエリの使用 MongoDB Server」を参照してください。
例
次の例では、ドキュメントのコレクションを昇順にページ分割します。
// Paginates through list of plants // in ascending order by plant name (A -> Z) async function paginateCollectionAscending( collection, nPerPage, startValue ) { const pipeline = [{ $sort: { name: 1 } }, { $limit: nPerPage }]; // If not starting from the beginning of the collection, // only match documents greater than the previous greatest value. if (startValue !== undefined) { pipeline.unshift({ $match: { name: { $gt: startValue }, }, }); } const results = await collection.aggregate(pipeline); return results; } // Number of results to show on each page const resultsPerPage = 3; const pageOneResults = await paginateCollectionAscending( plants, resultsPerPage ); const pageTwoStartValue = pageOneResults[pageOneResults.length - 1].name; const pageTwoResults = await paginateCollectionAscending( plants, resultsPerPage, pageTwoStartValue ); // ... can keep paginating for as many plants as there are in the collection
プロジェクト ドキュメント フィールド
$projectステージを使用して、ドキュメントから特定のフィールドを含めたり省略したり、集計演算子を使用して新しいフィールドを計算したりできます。 プロジェクションは、次の 2 つの方法で機能します。
値により 1 のフィールドが明示的に含められます。 これには、指定されていないすべてのフィールドを暗黙的に除外するという副作用があります。
値が 0 のフィールドを暗黙的に除外します。これには、指定されていないすべてのフィールドが暗黙的に含まれるという副作用があります。
これらの 2 つのプロジェクション方法は相互に排他的です。つまり、フィールドを明示的に含める場合は、フィールドを明示的に除外することはできません。また、その逆も同様です。
注意
_id
フィールドは特別なケースで、明示的に指定されない限り、すべてのクエリに常に含まれます。 このため、 0
値を持つ_id
フィールドを除外しながら、同時に_partition
などの他のフィールドを1
とともに含めることができます。 _id
フィールドを除外するという特別なケースのみ、1 つの$project
ステージで除外と包含の両方が許可されます。
{ "$project": { "<Field Name>": <0 | 1 | Expression>, ... } }
例
次の$project
ステージでは、 _id
フィールドが省略され、 name
フィールドが含まれ、 storeNumber
という名前の新しいフィールドが作成されます。 storeNumber
は 2 つの集計演算子を使用して生成されます。
$split
は、_partition
値をスペース文字で囲む 2 つのstringセグメントに分割します。 たとえば、この方法で分割された値「Store 42」は、「store」と「42」の 2 つの要素を含む配列を返します。$arrayElemAt
は、2 番目の引数に基づいて配列から特定の要素を選択します。 この場合、値1
は、0
の配列インデックス以降、$split
演算子によって生成された配列から 2 番目の要素を選択します。 たとえば、この操作に渡される値 ["store", "42"] は "42" の値を返します。
const result = await plants.aggregate([ { $project: { _id: 0, name: 1, storeNumber: { $arrayElemAt: [{ $split: ["$_partition", " "] }, 1], }, }, }, ]); console.log(result);
[ { "name": "venus flytrap", "storeNumber": "42" }, { "name": "thai basil", "storeNumber": "42" }, { "name": "helianthus", "storeNumber": "42" }, { "name": "wisteria lilac", "storeNumber": "42" }, { "name": "daffodil", "storeNumber": "42" }, { "name": "sweet basil", "storeNumber": "47" } ]
ドキュメントへのフィールドの追加
$addFieldsステージを使用して、集計演算子を使用して計算された値を持つ新しいフィールドを追加できます。
{ $addFields: { <newField>: <expression>, ... } }
注意
$addFields
は$projectに似ていますが、フィールドを含めたり省略したりすることはできません。
例
次の$addFields
ステージでは、 storeNumber
という名前の新しいフィールドが作成されます。値は_partition
フィールドの値を変換する 2 つの集計演算子の出力です。
const result = await plants.aggregate([ { $addFields: { storeNumber: { $arrayElemAt: [{ $split: ["$_partition", " "] }, 1], }, }, }, ]); console.log(result);
[ { "_id": ObjectId("5f87976b7b800b285345a8c4"), "_partition": "Store 42", "color": "white", "name": "venus flytrap", "storeNumber": "42", "sunlight": "full", "type": "perennial" }, { "_id": ObjectId("5f87976b7b800b285345a8c6"), "_partition": "Store 42", "color": "green", "name": "thai basil", "storeNumber": "42", "sunlight": "partial", "type": "perennial" }, { "_id": ObjectId("5f87976b7b800b285345a8c7"), "_partition": "Store 42", "color": "yellow", "name": "helianthus", "storeNumber": "42", "sunlight": "full", "type": "annual" }, { "_id": ObjectId("5f87a0dffc9013565c233612"), "_partition": "Store 42", "color": "purple", "name": "wisteria lilac", "storeNumber": "42", "sunlight": "partial", "type": "perennial" }, { "_id": ObjectId("5f87a0dffc9013565c233613"), "_partition": "Store 42", "color": "yellow", "name": "daffodil", "storeNumber": "42", "sunlight": "full", "type": "perennial" }, { "_id": ObjectId("5f1f63055512f2cb67f460a3"), "_partition": "Store 47", "color": "green", "name": "sweet basil", "storeNumber": "47", "sunlight": "full", "type": "perennial" } ]
Unwind Array Values
$unwindステージを使用して、配列を含む単一のドキュメントを、その配列の個々の値を含む複数のドキュメントに変換できます。 配列フィールドを展開すると、MongoDB は配列フィールドの要素ごとに各ドキュメントを 1 回コピーしますが、コピーごとに配列値を配列要素に置き換えます。
{ $unwind: { path: <Array Field Path>, includeArrayIndex: <string>, preserveNullAndEmptyArrays: <boolean> } }
例
次の例では、各オブジェクトのtype
とcolor
の組み合わせに対して$unwind
ステージを使用します。 集計パイプラインには、次の手順があります。
$group
ステージを$addToSet
と併用して、コレクション内に発生するその花の種類のすべての色の配列を含む新しいフィールドcolors
を持つ各type
に新しいドキュメントを作成します。$unwind
ステージを使用して、タイプと色の組み合わせごとに個別のドキュメントを作成します。$sort
ステージを使用して、結果をアルファベット順にソートします。
const result = await plants.aggregate([ { $group: { _id: "$type", colors: { $addToSet: "$color" } } }, { $unwind: { path: "$colors" } }, { $sort: { _id: 1, colors: 1 } }, ]); console.log(result);
[ { "_id": "annual", "colors": "yellow" }, { "_id": "perennial", "colors": "green" }, { "_id": "perennial", "colors": "purple" }, { "_id": "perennial", "colors": "white" }, { "_id": "perennial", "colors": "yellow" }, ]