chub-dev 0.1.0 → 0.1.2-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -0
- package/bin/chub-mcp +2 -0
- package/dist/airtable/docs/database/javascript/DOC.md +1437 -0
- package/dist/airtable/docs/database/python/DOC.md +1735 -0
- package/dist/amplitude/docs/analytics/javascript/DOC.md +1282 -0
- package/dist/amplitude/docs/analytics/python/DOC.md +1199 -0
- package/dist/anthropic/docs/claude-api/javascript/DOC.md +503 -0
- package/dist/anthropic/docs/claude-api/python/DOC.md +389 -0
- package/dist/asana/docs/tasks/DOC.md +1396 -0
- package/dist/assemblyai/docs/transcription/DOC.md +1043 -0
- package/dist/atlassian/docs/confluence/javascript/DOC.md +1347 -0
- package/dist/atlassian/docs/confluence/python/DOC.md +1604 -0
- package/dist/auth0/docs/identity/javascript/DOC.md +968 -0
- package/dist/auth0/docs/identity/python/DOC.md +1199 -0
- package/dist/aws/docs/s3/javascript/DOC.md +1773 -0
- package/dist/aws/docs/s3/python/DOC.md +1807 -0
- package/dist/binance/docs/trading/javascript/DOC.md +1315 -0
- package/dist/binance/docs/trading/python/DOC.md +1454 -0
- package/dist/braintree/docs/gateway/javascript/DOC.md +1278 -0
- package/dist/braintree/docs/gateway/python/DOC.md +1179 -0
- package/dist/chromadb/docs/embeddings-db/javascript/DOC.md +1263 -0
- package/dist/chromadb/docs/embeddings-db/python/DOC.md +1707 -0
- package/dist/clerk/docs/auth/javascript/DOC.md +1220 -0
- package/dist/clerk/docs/auth/python/DOC.md +274 -0
- package/dist/cloudflare/docs/workers/javascript/DOC.md +918 -0
- package/dist/cloudflare/docs/workers/python/DOC.md +994 -0
- package/dist/cockroachdb/docs/distributed-db/DOC.md +1500 -0
- package/dist/cohere/docs/llm/DOC.md +1335 -0
- package/dist/datadog/docs/monitoring/javascript/DOC.md +1740 -0
- package/dist/datadog/docs/monitoring/python/DOC.md +1815 -0
- package/dist/deepgram/docs/speech/javascript/DOC.md +885 -0
- package/dist/deepgram/docs/speech/python/DOC.md +685 -0
- package/dist/deepl/docs/translation/javascript/DOC.md +887 -0
- package/dist/deepl/docs/translation/python/DOC.md +944 -0
- package/dist/deepseek/docs/llm/DOC.md +1220 -0
- package/dist/directus/docs/headless-cms/javascript/DOC.md +1128 -0
- package/dist/directus/docs/headless-cms/python/DOC.md +1276 -0
- package/dist/discord/docs/bot/javascript/DOC.md +1090 -0
- package/dist/discord/docs/bot/python/DOC.md +1130 -0
- package/dist/elasticsearch/docs/search/DOC.md +1634 -0
- package/dist/elevenlabs/docs/text-to-speech/javascript/DOC.md +336 -0
- package/dist/elevenlabs/docs/text-to-speech/python/DOC.md +552 -0
- package/dist/firebase/docs/auth/DOC.md +1015 -0
- package/dist/gemini/docs/genai/javascript/DOC.md +691 -0
- package/dist/gemini/docs/genai/python/DOC.md +555 -0
- package/dist/github/docs/octokit/DOC.md +1560 -0
- package/dist/google/docs/bigquery/javascript/DOC.md +1688 -0
- package/dist/google/docs/bigquery/python/DOC.md +1503 -0
- package/dist/hubspot/docs/crm/javascript/DOC.md +1805 -0
- package/dist/hubspot/docs/crm/python/DOC.md +2033 -0
- package/dist/huggingface/docs/transformers/DOC.md +948 -0
- package/dist/intercom/docs/messaging/javascript/DOC.md +1844 -0
- package/dist/intercom/docs/messaging/python/DOC.md +1797 -0
- package/dist/jira/docs/issues/javascript/DOC.md +1420 -0
- package/dist/jira/docs/issues/python/DOC.md +1492 -0
- package/dist/kafka/docs/streaming/javascript/DOC.md +1671 -0
- package/dist/kafka/docs/streaming/python/DOC.md +1464 -0
- package/dist/landingai-ade/docs/api/DOC.md +620 -0
- package/dist/landingai-ade/docs/sdk/python/DOC.md +489 -0
- package/dist/landingai-ade/docs/sdk/typescript/DOC.md +542 -0
- package/dist/landingai-ade/skills/SKILL.md +489 -0
- package/dist/launchdarkly/docs/feature-flags/javascript/DOC.md +1191 -0
- package/dist/launchdarkly/docs/feature-flags/python/DOC.md +1671 -0
- package/dist/linear/docs/tracker/DOC.md +1554 -0
- package/dist/livekit/docs/realtime/javascript/DOC.md +303 -0
- package/dist/livekit/docs/realtime/python/DOC.md +163 -0
- package/dist/mailchimp/docs/marketing/DOC.md +1420 -0
- package/dist/meilisearch/docs/search/DOC.md +1241 -0
- package/dist/microsoft/docs/onedrive/javascript/DOC.md +1421 -0
- package/dist/microsoft/docs/onedrive/python/DOC.md +1549 -0
- package/dist/mongodb/docs/atlas/DOC.md +2041 -0
- package/dist/notion/docs/workspace-api/javascript/DOC.md +1435 -0
- package/dist/notion/docs/workspace-api/python/DOC.md +1400 -0
- package/dist/okta/docs/identity/javascript/DOC.md +1171 -0
- package/dist/okta/docs/identity/python/DOC.md +1401 -0
- package/dist/openai/docs/chat/javascript/DOC.md +407 -0
- package/dist/openai/docs/chat/python/DOC.md +568 -0
- package/dist/paypal/docs/checkout/DOC.md +278 -0
- package/dist/pinecone/docs/sdk/javascript/DOC.md +984 -0
- package/dist/pinecone/docs/sdk/python/DOC.md +1395 -0
- package/dist/plaid/docs/banking/javascript/DOC.md +1163 -0
- package/dist/plaid/docs/banking/python/DOC.md +1203 -0
- package/dist/playwright-community/skills/login-flows/SKILL.md +108 -0
- package/dist/postmark/docs/transactional-email/DOC.md +1168 -0
- package/dist/prisma/docs/orm/javascript/DOC.md +1419 -0
- package/dist/prisma/docs/orm/python/DOC.md +1317 -0
- package/dist/qdrant/docs/vector-search/javascript/DOC.md +1221 -0
- package/dist/qdrant/docs/vector-search/python/DOC.md +1653 -0
- package/dist/rabbitmq/docs/message-queue/javascript/DOC.md +1193 -0
- package/dist/rabbitmq/docs/message-queue/python/DOC.md +1243 -0
- package/dist/razorpay/docs/payments/javascript/DOC.md +1219 -0
- package/dist/razorpay/docs/payments/python/DOC.md +1330 -0
- package/dist/redis/docs/key-value/javascript/DOC.md +1851 -0
- package/dist/redis/docs/key-value/python/DOC.md +2054 -0
- package/dist/registry.json +2817 -0
- package/dist/replicate/docs/model-hosting/DOC.md +1318 -0
- package/dist/resend/docs/email/DOC.md +1271 -0
- package/dist/salesforce/docs/crm/javascript/DOC.md +1241 -0
- package/dist/salesforce/docs/crm/python/DOC.md +1183 -0
- package/dist/search-index.json +1 -0
- package/dist/sendgrid/docs/email-api/javascript/DOC.md +371 -0
- package/dist/sendgrid/docs/email-api/python/DOC.md +656 -0
- package/dist/sentry/docs/error-tracking/javascript/DOC.md +1073 -0
- package/dist/sentry/docs/error-tracking/python/DOC.md +1309 -0
- package/dist/shopify/docs/storefront/DOC.md +457 -0
- package/dist/slack/docs/workspace/javascript/DOC.md +933 -0
- package/dist/slack/docs/workspace/python/DOC.md +271 -0
- package/dist/square/docs/payments/javascript/DOC.md +1855 -0
- package/dist/square/docs/payments/python/DOC.md +1728 -0
- package/dist/stripe/docs/api/DOC.md +1727 -0
- package/dist/stripe/docs/payments/DOC.md +1726 -0
- package/dist/stytch/docs/auth/javascript/DOC.md +1813 -0
- package/dist/stytch/docs/auth/python/DOC.md +1962 -0
- package/dist/supabase/docs/client/DOC.md +1606 -0
- package/dist/twilio/docs/messaging/python/DOC.md +469 -0
- package/dist/twilio/docs/messaging/typescript/DOC.md +946 -0
- package/dist/vercel/docs/platform/DOC.md +1940 -0
- package/dist/weaviate/docs/vector-db/javascript/DOC.md +1268 -0
- package/dist/weaviate/docs/vector-db/python/DOC.md +1388 -0
- package/dist/zendesk/docs/support/javascript/DOC.md +2150 -0
- package/dist/zendesk/docs/support/python/DOC.md +2297 -0
- package/package.json +22 -6
- package/skills/get-api-docs/SKILL.md +84 -0
- package/src/commands/annotate.js +83 -0
- package/src/commands/build.js +12 -1
- package/src/commands/feedback.js +150 -0
- package/src/commands/get.js +83 -42
- package/src/commands/search.js +7 -0
- package/src/index.js +43 -17
- package/src/lib/analytics.js +90 -0
- package/src/lib/annotations.js +57 -0
- package/src/lib/bm25.js +170 -0
- package/src/lib/cache.js +69 -6
- package/src/lib/config.js +8 -3
- package/src/lib/identity.js +99 -0
- package/src/lib/registry.js +103 -20
- package/src/lib/telemetry.js +86 -0
- package/src/mcp/server.js +177 -0
- package/src/mcp/tools.js +251 -0
|
@@ -0,0 +1,2041 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: atlas
|
|
3
|
+
description: "MongoDB Node.js driver for interacting with MongoDB Atlas databases using the official JavaScript/TypeScript SDK."
|
|
4
|
+
metadata:
|
|
5
|
+
languages: "javascript"
|
|
6
|
+
versions: "6.20.0"
|
|
7
|
+
updated-on: "2026-03-01"
|
|
8
|
+
source: maintainer
|
|
9
|
+
tags: "mongodb,atlas,database,nosql,driver"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# MongoDB Atlas Coding Guidelines (JavaScript/TypeScript)
|
|
13
|
+
|
|
14
|
+
You are a MongoDB Atlas coding expert. Help me with writing code using the MongoDB Node.js driver calling the official libraries and SDKs.
|
|
15
|
+
|
|
16
|
+
## Golden Rule: Use the Correct and Current SDK
|
|
17
|
+
|
|
18
|
+
Always use the official MongoDB Node.js driver for all MongoDB Atlas interactions.
|
|
19
|
+
|
|
20
|
+
- **Library Name:** MongoDB Node.js Driver
|
|
21
|
+
- **NPM Package:** `mongodb`
|
|
22
|
+
- **GitHub:** https://github.com/mongodb/node-mongodb-native
|
|
23
|
+
|
|
24
|
+
**Installation:**
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install mongodb
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Import Patterns:**
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
// ES6 import (recommended)
|
|
34
|
+
import { MongoClient } from 'mongodb';
|
|
35
|
+
|
|
36
|
+
// CommonJS require
|
|
37
|
+
const { MongoClient } = require('mongodb');
|
|
38
|
+
|
|
39
|
+
// Additional utilities
|
|
40
|
+
import { MongoClient, ObjectId, Timestamp } from 'mongodb';
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Do NOT use:**
|
|
44
|
+
- Deprecated MongoDB packages
|
|
45
|
+
- Third-party MongoDB wrappers (unless specifically requested)
|
|
46
|
+
- Old connection patterns from MongoDB driver v2 or v3
|
|
47
|
+
|
|
48
|
+
## Installation and Environment Setup
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npm install mongodb
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Environment Variables Setup:**
|
|
55
|
+
|
|
56
|
+
Create a `.env` file in your project root:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
MONGODB_URI=mongodb+srv://username:password@cluster.mongodb.net/database?retryWrites=true&w=majority
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Using dotenv for environment variables:**
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npm install dotenv
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
import 'dotenv/config';
|
|
70
|
+
import { MongoClient } from 'mongodb';
|
|
71
|
+
|
|
72
|
+
const uri = process.env.MONGODB_URI;
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Initialization and Connection
|
|
76
|
+
|
|
77
|
+
The MongoDB driver requires creating a `MongoClient` instance for all database operations.
|
|
78
|
+
|
|
79
|
+
**Basic Connection:**
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
import { MongoClient } from 'mongodb';
|
|
83
|
+
|
|
84
|
+
const uri = process.env.MONGODB_URI;
|
|
85
|
+
const client = new MongoClient(uri);
|
|
86
|
+
|
|
87
|
+
async function main() {
|
|
88
|
+
try {
|
|
89
|
+
await client.connect();
|
|
90
|
+
console.log('Connected to MongoDB Atlas');
|
|
91
|
+
|
|
92
|
+
const database = client.db('myDatabase');
|
|
93
|
+
const collection = database.collection('myCollection');
|
|
94
|
+
|
|
95
|
+
// Perform operations...
|
|
96
|
+
|
|
97
|
+
} finally {
|
|
98
|
+
await client.close();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
main().catch(console.error);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Connection with Options:**
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
import { MongoClient, ServerApiVersion } from 'mongodb';
|
|
109
|
+
|
|
110
|
+
const uri = process.env.MONGODB_URI;
|
|
111
|
+
|
|
112
|
+
const client = new MongoClient(uri, {
|
|
113
|
+
serverApi: {
|
|
114
|
+
version: ServerApiVersion.v1,
|
|
115
|
+
strict: true,
|
|
116
|
+
deprecationErrors: true,
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
async function run() {
|
|
121
|
+
try {
|
|
122
|
+
await client.connect();
|
|
123
|
+
await client.db('admin').command({ ping: 1 });
|
|
124
|
+
console.log('Pinged your deployment. Successfully connected to MongoDB!');
|
|
125
|
+
} finally {
|
|
126
|
+
await client.close();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
run().catch(console.error);
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Reusable Connection Pattern:**
|
|
134
|
+
|
|
135
|
+
```javascript
|
|
136
|
+
import { MongoClient } from 'mongodb';
|
|
137
|
+
|
|
138
|
+
let client;
|
|
139
|
+
let clientPromise;
|
|
140
|
+
|
|
141
|
+
const uri = process.env.MONGODB_URI;
|
|
142
|
+
const options = {};
|
|
143
|
+
|
|
144
|
+
if (process.env.NODE_ENV === 'development') {
|
|
145
|
+
// In development mode, use a global variable to preserve connection
|
|
146
|
+
if (!global._mongoClientPromise) {
|
|
147
|
+
client = new MongoClient(uri, options);
|
|
148
|
+
global._mongoClientPromise = client.connect();
|
|
149
|
+
}
|
|
150
|
+
clientPromise = global._mongoClientPromise;
|
|
151
|
+
} else {
|
|
152
|
+
// In production mode, create a new client
|
|
153
|
+
client = new MongoClient(uri, options);
|
|
154
|
+
clientPromise = client.connect();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export default clientPromise;
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## CRUD Operations
|
|
161
|
+
|
|
162
|
+
### Insert Documents
|
|
163
|
+
|
|
164
|
+
**Insert One Document:**
|
|
165
|
+
|
|
166
|
+
```javascript
|
|
167
|
+
import { MongoClient } from 'mongodb';
|
|
168
|
+
|
|
169
|
+
const client = new MongoClient(process.env.MONGODB_URI);
|
|
170
|
+
|
|
171
|
+
async function insertDocument() {
|
|
172
|
+
try {
|
|
173
|
+
await client.connect();
|
|
174
|
+
const database = client.db('sample_db');
|
|
175
|
+
const collection = database.collection('users');
|
|
176
|
+
|
|
177
|
+
const doc = {
|
|
178
|
+
name: 'John Doe',
|
|
179
|
+
email: 'john@example.com',
|
|
180
|
+
age: 30,
|
|
181
|
+
createdAt: new Date()
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const result = await collection.insertOne(doc);
|
|
185
|
+
console.log(`Document inserted with _id: ${result.insertedId}`);
|
|
186
|
+
|
|
187
|
+
} finally {
|
|
188
|
+
await client.close();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
insertDocument().catch(console.error);
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**Insert Multiple Documents:**
|
|
196
|
+
|
|
197
|
+
```javascript
|
|
198
|
+
async function insertMultipleDocuments() {
|
|
199
|
+
try {
|
|
200
|
+
await client.connect();
|
|
201
|
+
const database = client.db('sample_db');
|
|
202
|
+
const collection = database.collection('users');
|
|
203
|
+
|
|
204
|
+
const docs = [
|
|
205
|
+
{ name: 'Alice', email: 'alice@example.com', age: 25 },
|
|
206
|
+
{ name: 'Bob', email: 'bob@example.com', age: 32 },
|
|
207
|
+
{ name: 'Charlie', email: 'charlie@example.com', age: 28 }
|
|
208
|
+
];
|
|
209
|
+
|
|
210
|
+
const result = await collection.insertMany(docs);
|
|
211
|
+
console.log(`${result.insertedCount} documents inserted`);
|
|
212
|
+
console.log('Inserted IDs:', result.insertedIds);
|
|
213
|
+
|
|
214
|
+
} finally {
|
|
215
|
+
await client.close();
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
insertMultipleDocuments().catch(console.error);
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Insert with Options:**
|
|
223
|
+
|
|
224
|
+
```javascript
|
|
225
|
+
async function insertWithOptions() {
|
|
226
|
+
try {
|
|
227
|
+
await client.connect();
|
|
228
|
+
const database = client.db('sample_db');
|
|
229
|
+
const collection = database.collection('users');
|
|
230
|
+
|
|
231
|
+
const doc = { name: 'David', email: 'david@example.com' };
|
|
232
|
+
|
|
233
|
+
const result = await collection.insertOne(doc, {
|
|
234
|
+
writeConcern: { w: 'majority', wtimeout: 5000 }
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
console.log(`Document inserted: ${result.insertedId}`);
|
|
238
|
+
|
|
239
|
+
} finally {
|
|
240
|
+
await client.close();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
insertWithOptions().catch(console.error);
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Find Documents
|
|
248
|
+
|
|
249
|
+
**Find All Documents:**
|
|
250
|
+
|
|
251
|
+
```javascript
|
|
252
|
+
async function findAllDocuments() {
|
|
253
|
+
try {
|
|
254
|
+
await client.connect();
|
|
255
|
+
const database = client.db('sample_db');
|
|
256
|
+
const collection = database.collection('users');
|
|
257
|
+
|
|
258
|
+
const cursor = collection.find({});
|
|
259
|
+
const documents = await cursor.toArray();
|
|
260
|
+
|
|
261
|
+
console.log('All documents:', documents);
|
|
262
|
+
|
|
263
|
+
} finally {
|
|
264
|
+
await client.close();
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
findAllDocuments().catch(console.error);
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**Find with Filter:**
|
|
272
|
+
|
|
273
|
+
```javascript
|
|
274
|
+
async function findWithFilter() {
|
|
275
|
+
try {
|
|
276
|
+
await client.connect();
|
|
277
|
+
const database = client.db('sample_db');
|
|
278
|
+
const collection = database.collection('users');
|
|
279
|
+
|
|
280
|
+
// Find users older than 25
|
|
281
|
+
const query = { age: { $gt: 25 } };
|
|
282
|
+
const cursor = collection.find(query);
|
|
283
|
+
const results = await cursor.toArray();
|
|
284
|
+
|
|
285
|
+
console.log('Users older than 25:', results);
|
|
286
|
+
|
|
287
|
+
} finally {
|
|
288
|
+
await client.close();
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
findWithFilter().catch(console.error);
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
**Find One Document:**
|
|
296
|
+
|
|
297
|
+
```javascript
|
|
298
|
+
async function findOneDocument() {
|
|
299
|
+
try {
|
|
300
|
+
await client.connect();
|
|
301
|
+
const database = client.db('sample_db');
|
|
302
|
+
const collection = database.collection('users');
|
|
303
|
+
|
|
304
|
+
const query = { email: 'john@example.com' };
|
|
305
|
+
const user = await collection.findOne(query);
|
|
306
|
+
|
|
307
|
+
if (user) {
|
|
308
|
+
console.log('Found user:', user);
|
|
309
|
+
} else {
|
|
310
|
+
console.log('User not found');
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
} finally {
|
|
314
|
+
await client.close();
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
findOneDocument().catch(console.error);
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
**Find with Projection:**
|
|
322
|
+
|
|
323
|
+
```javascript
|
|
324
|
+
async function findWithProjection() {
|
|
325
|
+
try {
|
|
326
|
+
await client.connect();
|
|
327
|
+
const database = client.db('sample_db');
|
|
328
|
+
const collection = database.collection('users');
|
|
329
|
+
|
|
330
|
+
const query = { age: { $gte: 25 } };
|
|
331
|
+
const options = {
|
|
332
|
+
projection: { _id: 0, name: 1, email: 1 }
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
const cursor = collection.find(query, options);
|
|
336
|
+
const results = await cursor.toArray();
|
|
337
|
+
|
|
338
|
+
console.log('Users (name and email only):', results);
|
|
339
|
+
|
|
340
|
+
} finally {
|
|
341
|
+
await client.close();
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
findWithProjection().catch(console.error);
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
**Find with Sort, Limit, and Skip:**
|
|
349
|
+
|
|
350
|
+
```javascript
|
|
351
|
+
async function findWithSortLimitSkip() {
|
|
352
|
+
try {
|
|
353
|
+
await client.connect();
|
|
354
|
+
const database = client.db('sample_db');
|
|
355
|
+
const collection = database.collection('users');
|
|
356
|
+
|
|
357
|
+
const cursor = collection.find({})
|
|
358
|
+
.sort({ age: -1 }) // Sort by age descending
|
|
359
|
+
.limit(10) // Limit to 10 results
|
|
360
|
+
.skip(5); // Skip first 5 results
|
|
361
|
+
|
|
362
|
+
const results = await cursor.toArray();
|
|
363
|
+
|
|
364
|
+
console.log('Sorted and paginated results:', results);
|
|
365
|
+
|
|
366
|
+
} finally {
|
|
367
|
+
await client.close();
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
findWithSortLimitSkip().catch(console.error);
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
**Pagination Pattern:**
|
|
375
|
+
|
|
376
|
+
```javascript
|
|
377
|
+
async function paginateDocuments(page = 1, pageSize = 10) {
|
|
378
|
+
try {
|
|
379
|
+
await client.connect();
|
|
380
|
+
const database = client.db('sample_db');
|
|
381
|
+
const collection = database.collection('users');
|
|
382
|
+
|
|
383
|
+
const skip = (page - 1) * pageSize;
|
|
384
|
+
|
|
385
|
+
const cursor = collection.find({})
|
|
386
|
+
.sort({ createdAt: -1 })
|
|
387
|
+
.skip(skip)
|
|
388
|
+
.limit(pageSize);
|
|
389
|
+
|
|
390
|
+
const documents = await cursor.toArray();
|
|
391
|
+
const total = await collection.countDocuments({});
|
|
392
|
+
|
|
393
|
+
return {
|
|
394
|
+
documents,
|
|
395
|
+
page,
|
|
396
|
+
pageSize,
|
|
397
|
+
totalPages: Math.ceil(total / pageSize),
|
|
398
|
+
totalDocuments: total
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
} finally {
|
|
402
|
+
await client.close();
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
paginateDocuments(1, 20).then(console.log).catch(console.error);
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
**Cursor-Based Pagination (Better Performance):**
|
|
410
|
+
|
|
411
|
+
```javascript
|
|
412
|
+
async function cursorPagination(lastId = null, pageSize = 10) {
|
|
413
|
+
try {
|
|
414
|
+
await client.connect();
|
|
415
|
+
const database = client.db('sample_db');
|
|
416
|
+
const collection = database.collection('users');
|
|
417
|
+
|
|
418
|
+
const query = lastId ? { _id: { $gt: lastId } } : {};
|
|
419
|
+
|
|
420
|
+
const cursor = collection.find(query)
|
|
421
|
+
.sort({ _id: 1 })
|
|
422
|
+
.limit(pageSize);
|
|
423
|
+
|
|
424
|
+
const documents = await cursor.toArray();
|
|
425
|
+
|
|
426
|
+
return {
|
|
427
|
+
documents,
|
|
428
|
+
nextCursor: documents.length > 0
|
|
429
|
+
? documents[documents.length - 1]._id
|
|
430
|
+
: null
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
} finally {
|
|
434
|
+
await client.close();
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
cursorPagination(null, 20).then(console.log).catch(console.error);
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### Update Documents
|
|
442
|
+
|
|
443
|
+
**Update One Document:**
|
|
444
|
+
|
|
445
|
+
```javascript
|
|
446
|
+
async function updateOneDocument() {
|
|
447
|
+
try {
|
|
448
|
+
await client.connect();
|
|
449
|
+
const database = client.db('sample_db');
|
|
450
|
+
const collection = database.collection('users');
|
|
451
|
+
|
|
452
|
+
const filter = { email: 'john@example.com' };
|
|
453
|
+
const update = {
|
|
454
|
+
$set: { age: 31, updatedAt: new Date() }
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
const result = await collection.updateOne(filter, update);
|
|
458
|
+
|
|
459
|
+
console.log(`${result.matchedCount} document(s) matched the filter`);
|
|
460
|
+
console.log(`${result.modifiedCount} document(s) updated`);
|
|
461
|
+
|
|
462
|
+
} finally {
|
|
463
|
+
await client.close();
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
updateOneDocument().catch(console.error);
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
**Update Multiple Documents:**
|
|
471
|
+
|
|
472
|
+
```javascript
|
|
473
|
+
async function updateManyDocuments() {
|
|
474
|
+
try {
|
|
475
|
+
await client.connect();
|
|
476
|
+
const database = client.db('sample_db');
|
|
477
|
+
const collection = database.collection('users');
|
|
478
|
+
|
|
479
|
+
const filter = { age: { $lt: 30 } };
|
|
480
|
+
const update = {
|
|
481
|
+
$set: { category: 'young', updatedAt: new Date() }
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
const result = await collection.updateMany(filter, update);
|
|
485
|
+
|
|
486
|
+
console.log(`${result.matchedCount} document(s) matched`);
|
|
487
|
+
console.log(`${result.modifiedCount} document(s) updated`);
|
|
488
|
+
|
|
489
|
+
} finally {
|
|
490
|
+
await client.close();
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
updateManyDocuments().catch(console.error);
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
**Update with Upsert:**
|
|
498
|
+
|
|
499
|
+
```javascript
|
|
500
|
+
async function updateWithUpsert() {
|
|
501
|
+
try {
|
|
502
|
+
await client.connect();
|
|
503
|
+
const database = client.db('sample_db');
|
|
504
|
+
const collection = database.collection('users');
|
|
505
|
+
|
|
506
|
+
const filter = { email: 'newuser@example.com' };
|
|
507
|
+
const update = {
|
|
508
|
+
$set: {
|
|
509
|
+
name: 'New User',
|
|
510
|
+
email: 'newuser@example.com',
|
|
511
|
+
age: 22,
|
|
512
|
+
createdAt: new Date()
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
const options = { upsert: true };
|
|
517
|
+
const result = await collection.updateOne(filter, update, options);
|
|
518
|
+
|
|
519
|
+
if (result.upsertedId) {
|
|
520
|
+
console.log(`Document inserted with _id: ${result.upsertedId}`);
|
|
521
|
+
} else {
|
|
522
|
+
console.log(`${result.modifiedCount} document(s) updated`);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
} finally {
|
|
526
|
+
await client.close();
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
updateWithUpsert().catch(console.error);
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
**Update Operators:**
|
|
534
|
+
|
|
535
|
+
```javascript
|
|
536
|
+
async function updateOperators() {
|
|
537
|
+
try {
|
|
538
|
+
await client.connect();
|
|
539
|
+
const database = client.db('sample_db');
|
|
540
|
+
const collection = database.collection('users');
|
|
541
|
+
|
|
542
|
+
const filter = { email: 'john@example.com' };
|
|
543
|
+
const update = {
|
|
544
|
+
$set: { status: 'active' },
|
|
545
|
+
$inc: { loginCount: 1 },
|
|
546
|
+
$push: { tags: 'premium' },
|
|
547
|
+
$currentDate: { lastModified: true }
|
|
548
|
+
};
|
|
549
|
+
|
|
550
|
+
const result = await collection.updateOne(filter, update);
|
|
551
|
+
console.log(`${result.modifiedCount} document(s) updated`);
|
|
552
|
+
|
|
553
|
+
} finally {
|
|
554
|
+
await client.close();
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
updateOperators().catch(console.error);
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
**Replace Document:**
|
|
562
|
+
|
|
563
|
+
```javascript
|
|
564
|
+
async function replaceDocument() {
|
|
565
|
+
try {
|
|
566
|
+
await client.connect();
|
|
567
|
+
const database = client.db('sample_db');
|
|
568
|
+
const collection = database.collection('users');
|
|
569
|
+
|
|
570
|
+
const filter = { email: 'john@example.com' };
|
|
571
|
+
const replacement = {
|
|
572
|
+
name: 'John Doe Updated',
|
|
573
|
+
email: 'john@example.com',
|
|
574
|
+
age: 31,
|
|
575
|
+
status: 'active',
|
|
576
|
+
updatedAt: new Date()
|
|
577
|
+
};
|
|
578
|
+
|
|
579
|
+
const result = await collection.replaceOne(filter, replacement);
|
|
580
|
+
console.log(`${result.modifiedCount} document(s) replaced`);
|
|
581
|
+
|
|
582
|
+
} finally {
|
|
583
|
+
await client.close();
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
replaceDocument().catch(console.error);
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
**Find and Modify:**
|
|
591
|
+
|
|
592
|
+
```javascript
|
|
593
|
+
async function findAndModify() {
|
|
594
|
+
try {
|
|
595
|
+
await client.connect();
|
|
596
|
+
const database = client.db('sample_db');
|
|
597
|
+
const collection = database.collection('users');
|
|
598
|
+
|
|
599
|
+
const filter = { email: 'john@example.com' };
|
|
600
|
+
const update = { $inc: { age: 1 } };
|
|
601
|
+
const options = {
|
|
602
|
+
returnDocument: 'after', // Return the updated document
|
|
603
|
+
upsert: false
|
|
604
|
+
};
|
|
605
|
+
|
|
606
|
+
const result = await collection.findOneAndUpdate(filter, update, options);
|
|
607
|
+
|
|
608
|
+
if (result) {
|
|
609
|
+
console.log('Updated document:', result);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
} finally {
|
|
613
|
+
await client.close();
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
findAndModify().catch(console.error);
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
### Delete Documents
|
|
621
|
+
|
|
622
|
+
**Delete One Document:**
|
|
623
|
+
|
|
624
|
+
```javascript
|
|
625
|
+
async function deleteOneDocument() {
|
|
626
|
+
try {
|
|
627
|
+
await client.connect();
|
|
628
|
+
const database = client.db('sample_db');
|
|
629
|
+
const collection = database.collection('users');
|
|
630
|
+
|
|
631
|
+
const filter = { email: 'john@example.com' };
|
|
632
|
+
const result = await collection.deleteOne(filter);
|
|
633
|
+
|
|
634
|
+
console.log(`${result.deletedCount} document(s) deleted`);
|
|
635
|
+
|
|
636
|
+
} finally {
|
|
637
|
+
await client.close();
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
deleteOneDocument().catch(console.error);
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
**Delete Multiple Documents:**
|
|
645
|
+
|
|
646
|
+
```javascript
|
|
647
|
+
async function deleteManyDocuments() {
|
|
648
|
+
try {
|
|
649
|
+
await client.connect();
|
|
650
|
+
const database = client.db('sample_db');
|
|
651
|
+
const collection = database.collection('users');
|
|
652
|
+
|
|
653
|
+
const filter = { age: { $lt: 18 } };
|
|
654
|
+
const result = await collection.deleteMany(filter);
|
|
655
|
+
|
|
656
|
+
console.log(`${result.deletedCount} document(s) deleted`);
|
|
657
|
+
|
|
658
|
+
} finally {
|
|
659
|
+
await client.close();
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
deleteManyDocuments().catch(console.error);
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
**Find and Delete:**
|
|
667
|
+
|
|
668
|
+
```javascript
|
|
669
|
+
async function findAndDelete() {
|
|
670
|
+
try {
|
|
671
|
+
await client.connect();
|
|
672
|
+
const database = client.db('sample_db');
|
|
673
|
+
const collection = database.collection('users');
|
|
674
|
+
|
|
675
|
+
const filter = { email: 'john@example.com' };
|
|
676
|
+
const options = {
|
|
677
|
+
sort: { createdAt: -1 }
|
|
678
|
+
};
|
|
679
|
+
|
|
680
|
+
const result = await collection.findOneAndDelete(filter, options);
|
|
681
|
+
|
|
682
|
+
if (result) {
|
|
683
|
+
console.log('Deleted document:', result);
|
|
684
|
+
} else {
|
|
685
|
+
console.log('No document found to delete');
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
} finally {
|
|
689
|
+
await client.close();
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
findAndDelete().catch(console.error);
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
## Aggregation Pipeline
|
|
697
|
+
|
|
698
|
+
**Basic Aggregation:**
|
|
699
|
+
|
|
700
|
+
```javascript
|
|
701
|
+
async function basicAggregation() {
|
|
702
|
+
try {
|
|
703
|
+
await client.connect();
|
|
704
|
+
const database = client.db('sample_db');
|
|
705
|
+
const collection = database.collection('users');
|
|
706
|
+
|
|
707
|
+
const pipeline = [
|
|
708
|
+
{ $match: { age: { $gte: 25 } } },
|
|
709
|
+
{ $group: {
|
|
710
|
+
_id: '$status',
|
|
711
|
+
count: { $sum: 1 },
|
|
712
|
+
avgAge: { $avg: '$age' }
|
|
713
|
+
}
|
|
714
|
+
},
|
|
715
|
+
{ $sort: { count: -1 } }
|
|
716
|
+
];
|
|
717
|
+
|
|
718
|
+
const results = await collection.aggregate(pipeline).toArray();
|
|
719
|
+
console.log('Aggregation results:', results);
|
|
720
|
+
|
|
721
|
+
} finally {
|
|
722
|
+
await client.close();
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
basicAggregation().catch(console.error);
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
**Advanced Aggregation with Multiple Stages:**
|
|
730
|
+
|
|
731
|
+
```javascript
|
|
732
|
+
async function advancedAggregation() {
|
|
733
|
+
try {
|
|
734
|
+
await client.connect();
|
|
735
|
+
const database = client.db('sample_db');
|
|
736
|
+
const collection = database.collection('orders');
|
|
737
|
+
|
|
738
|
+
const pipeline = [
|
|
739
|
+
{
|
|
740
|
+
$match: {
|
|
741
|
+
status: 'completed',
|
|
742
|
+
createdAt: { $gte: new Date('2024-01-01') }
|
|
743
|
+
}
|
|
744
|
+
},
|
|
745
|
+
{
|
|
746
|
+
$group: {
|
|
747
|
+
_id: {
|
|
748
|
+
year: { $year: '$createdAt' },
|
|
749
|
+
month: { $month: '$createdAt' }
|
|
750
|
+
},
|
|
751
|
+
totalSales: { $sum: '$amount' },
|
|
752
|
+
orderCount: { $sum: 1 },
|
|
753
|
+
avgOrderValue: { $avg: '$amount' }
|
|
754
|
+
}
|
|
755
|
+
},
|
|
756
|
+
{
|
|
757
|
+
$sort: { '_id.year': 1, '_id.month': 1 }
|
|
758
|
+
},
|
|
759
|
+
{
|
|
760
|
+
$project: {
|
|
761
|
+
_id: 0,
|
|
762
|
+
year: '$_id.year',
|
|
763
|
+
month: '$_id.month',
|
|
764
|
+
totalSales: 1,
|
|
765
|
+
orderCount: 1,
|
|
766
|
+
avgOrderValue: { $round: ['$avgOrderValue', 2] }
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
];
|
|
770
|
+
|
|
771
|
+
const results = await collection.aggregate(pipeline).toArray();
|
|
772
|
+
console.log('Sales report:', results);
|
|
773
|
+
|
|
774
|
+
} finally {
|
|
775
|
+
await client.close();
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
advancedAggregation().catch(console.error);
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
**Aggregation with $lookup (Join):**
|
|
783
|
+
|
|
784
|
+
```javascript
|
|
785
|
+
async function aggregationWithLookup() {
|
|
786
|
+
try {
|
|
787
|
+
await client.connect();
|
|
788
|
+
const database = client.db('sample_db');
|
|
789
|
+
const collection = database.collection('orders');
|
|
790
|
+
|
|
791
|
+
const pipeline = [
|
|
792
|
+
{
|
|
793
|
+
$lookup: {
|
|
794
|
+
from: 'users',
|
|
795
|
+
localField: 'userId',
|
|
796
|
+
foreignField: '_id',
|
|
797
|
+
as: 'userDetails'
|
|
798
|
+
}
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
$unwind: '$userDetails'
|
|
802
|
+
},
|
|
803
|
+
{
|
|
804
|
+
$project: {
|
|
805
|
+
orderNumber: 1,
|
|
806
|
+
amount: 1,
|
|
807
|
+
userName: '$userDetails.name',
|
|
808
|
+
userEmail: '$userDetails.email'
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
];
|
|
812
|
+
|
|
813
|
+
const results = await collection.aggregate(pipeline).toArray();
|
|
814
|
+
console.log('Orders with user details:', results);
|
|
815
|
+
|
|
816
|
+
} finally {
|
|
817
|
+
await client.close();
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
aggregationWithLookup().catch(console.error);
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
**Aggregation with $facet (Multiple Pipelines):**
|
|
825
|
+
|
|
826
|
+
```javascript
|
|
827
|
+
async function aggregationWithFacet() {
|
|
828
|
+
try {
|
|
829
|
+
await client.connect();
|
|
830
|
+
const database = client.db('sample_db');
|
|
831
|
+
const collection = database.collection('products');
|
|
832
|
+
|
|
833
|
+
const pipeline = [
|
|
834
|
+
{
|
|
835
|
+
$facet: {
|
|
836
|
+
categoryCounts: [
|
|
837
|
+
{ $group: { _id: '$category', count: { $sum: 1 } } },
|
|
838
|
+
{ $sort: { count: -1 } }
|
|
839
|
+
],
|
|
840
|
+
priceStats: [
|
|
841
|
+
{
|
|
842
|
+
$group: {
|
|
843
|
+
_id: null,
|
|
844
|
+
avgPrice: { $avg: '$price' },
|
|
845
|
+
minPrice: { $min: '$price' },
|
|
846
|
+
maxPrice: { $max: '$price' }
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
],
|
|
850
|
+
topProducts: [
|
|
851
|
+
{ $sort: { sales: -1 } },
|
|
852
|
+
{ $limit: 5 },
|
|
853
|
+
{ $project: { name: 1, sales: 1, price: 1 } }
|
|
854
|
+
]
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
];
|
|
858
|
+
|
|
859
|
+
const results = await collection.aggregate(pipeline).toArray();
|
|
860
|
+
console.log('Product analytics:', results[0]);
|
|
861
|
+
|
|
862
|
+
} finally {
|
|
863
|
+
await client.close();
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
aggregationWithFacet().catch(console.error);
|
|
868
|
+
```
|
|
869
|
+
|
|
870
|
+
## Indexes
|
|
871
|
+
|
|
872
|
+
**Create Single Field Index:**
|
|
873
|
+
|
|
874
|
+
```javascript
|
|
875
|
+
async function createIndex() {
|
|
876
|
+
try {
|
|
877
|
+
await client.connect();
|
|
878
|
+
const database = client.db('sample_db');
|
|
879
|
+
const collection = database.collection('users');
|
|
880
|
+
|
|
881
|
+
const result = await collection.createIndex({ email: 1 });
|
|
882
|
+
console.log(`Index created: ${result}`);
|
|
883
|
+
|
|
884
|
+
} finally {
|
|
885
|
+
await client.close();
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
createIndex().catch(console.error);
|
|
890
|
+
```
|
|
891
|
+
|
|
892
|
+
**Create Compound Index:**
|
|
893
|
+
|
|
894
|
+
```javascript
|
|
895
|
+
async function createCompoundIndex() {
|
|
896
|
+
try {
|
|
897
|
+
await client.connect();
|
|
898
|
+
const database = client.db('sample_db');
|
|
899
|
+
const collection = database.collection('users');
|
|
900
|
+
|
|
901
|
+
const result = await collection.createIndex(
|
|
902
|
+
{ lastName: 1, firstName: 1 }
|
|
903
|
+
);
|
|
904
|
+
console.log(`Compound index created: ${result}`);
|
|
905
|
+
|
|
906
|
+
} finally {
|
|
907
|
+
await client.close();
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
createCompoundIndex().catch(console.error);
|
|
912
|
+
```
|
|
913
|
+
|
|
914
|
+
**Create Unique Index:**
|
|
915
|
+
|
|
916
|
+
```javascript
|
|
917
|
+
async function createUniqueIndex() {
|
|
918
|
+
try {
|
|
919
|
+
await client.connect();
|
|
920
|
+
const database = client.db('sample_db');
|
|
921
|
+
const collection = database.collection('users');
|
|
922
|
+
|
|
923
|
+
const result = await collection.createIndex(
|
|
924
|
+
{ email: 1 },
|
|
925
|
+
{ unique: true }
|
|
926
|
+
);
|
|
927
|
+
console.log(`Unique index created: ${result}`);
|
|
928
|
+
|
|
929
|
+
} finally {
|
|
930
|
+
await client.close();
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
createUniqueIndex().catch(console.error);
|
|
935
|
+
```
|
|
936
|
+
|
|
937
|
+
**Create Text Index:**
|
|
938
|
+
|
|
939
|
+
```javascript
|
|
940
|
+
async function createTextIndex() {
|
|
941
|
+
try {
|
|
942
|
+
await client.connect();
|
|
943
|
+
const database = client.db('sample_db');
|
|
944
|
+
const collection = database.collection('articles');
|
|
945
|
+
|
|
946
|
+
const result = await collection.createIndex(
|
|
947
|
+
{ title: 'text', content: 'text' }
|
|
948
|
+
);
|
|
949
|
+
console.log(`Text index created: ${result}`);
|
|
950
|
+
|
|
951
|
+
} finally {
|
|
952
|
+
await client.close();
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
createTextIndex().catch(console.error);
|
|
957
|
+
```
|
|
958
|
+
|
|
959
|
+
**Text Search Query:**
|
|
960
|
+
|
|
961
|
+
```javascript
|
|
962
|
+
async function textSearch() {
|
|
963
|
+
try {
|
|
964
|
+
await client.connect();
|
|
965
|
+
const database = client.db('sample_db');
|
|
966
|
+
const collection = database.collection('articles');
|
|
967
|
+
|
|
968
|
+
const query = { $text: { $search: 'mongodb tutorial' } };
|
|
969
|
+
const projection = { score: { $meta: 'textScore' } };
|
|
970
|
+
|
|
971
|
+
const cursor = collection
|
|
972
|
+
.find(query, { projection })
|
|
973
|
+
.sort({ score: { $meta: 'textScore' } });
|
|
974
|
+
|
|
975
|
+
const results = await cursor.toArray();
|
|
976
|
+
console.log('Search results:', results);
|
|
977
|
+
|
|
978
|
+
} finally {
|
|
979
|
+
await client.close();
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
textSearch().catch(console.error);
|
|
984
|
+
```
|
|
985
|
+
|
|
986
|
+
**Create 2dsphere Index (Geospatial):**
|
|
987
|
+
|
|
988
|
+
```javascript
|
|
989
|
+
async function createGeospatialIndex() {
|
|
990
|
+
try {
|
|
991
|
+
await client.connect();
|
|
992
|
+
const database = client.db('sample_db');
|
|
993
|
+
const collection = database.collection('locations');
|
|
994
|
+
|
|
995
|
+
const result = await collection.createIndex(
|
|
996
|
+
{ location: '2dsphere' }
|
|
997
|
+
);
|
|
998
|
+
console.log(`Geospatial index created: ${result}`);
|
|
999
|
+
|
|
1000
|
+
} finally {
|
|
1001
|
+
await client.close();
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
createGeospatialIndex().catch(console.error);
|
|
1006
|
+
```
|
|
1007
|
+
|
|
1008
|
+
**Geospatial Query ($near):**
|
|
1009
|
+
|
|
1010
|
+
```javascript
|
|
1011
|
+
async function geospatialNearQuery() {
|
|
1012
|
+
try {
|
|
1013
|
+
await client.connect();
|
|
1014
|
+
const database = client.db('sample_db');
|
|
1015
|
+
const collection = database.collection('locations');
|
|
1016
|
+
|
|
1017
|
+
const query = {
|
|
1018
|
+
location: {
|
|
1019
|
+
$near: {
|
|
1020
|
+
$geometry: {
|
|
1021
|
+
type: 'Point',
|
|
1022
|
+
coordinates: [-73.9667, 40.78] // [longitude, latitude]
|
|
1023
|
+
},
|
|
1024
|
+
$maxDistance: 5000 // 5km in meters
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
};
|
|
1028
|
+
|
|
1029
|
+
const results = await collection.find(query).limit(10).toArray();
|
|
1030
|
+
console.log('Nearby locations:', results);
|
|
1031
|
+
|
|
1032
|
+
} finally {
|
|
1033
|
+
await client.close();
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
geospatialNearQuery().catch(console.error);
|
|
1038
|
+
```
|
|
1039
|
+
|
|
1040
|
+
**Geospatial Query ($geoWithin):**
|
|
1041
|
+
|
|
1042
|
+
```javascript
|
|
1043
|
+
async function geospatialWithinQuery() {
|
|
1044
|
+
try {
|
|
1045
|
+
await client.connect();
|
|
1046
|
+
const database = client.db('sample_db');
|
|
1047
|
+
const collection = database.collection('locations');
|
|
1048
|
+
|
|
1049
|
+
const query = {
|
|
1050
|
+
location: {
|
|
1051
|
+
$geoWithin: {
|
|
1052
|
+
$geometry: {
|
|
1053
|
+
type: 'Polygon',
|
|
1054
|
+
coordinates: [[
|
|
1055
|
+
[-74.0, 40.7],
|
|
1056
|
+
[-73.9, 40.7],
|
|
1057
|
+
[-73.9, 40.8],
|
|
1058
|
+
[-74.0, 40.8],
|
|
1059
|
+
[-74.0, 40.7]
|
|
1060
|
+
]]
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
};
|
|
1065
|
+
|
|
1066
|
+
const results = await collection.find(query).toArray();
|
|
1067
|
+
console.log('Locations within polygon:', results);
|
|
1068
|
+
|
|
1069
|
+
} finally {
|
|
1070
|
+
await client.close();
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
geospatialWithinQuery().catch(console.error);
|
|
1075
|
+
```
|
|
1076
|
+
|
|
1077
|
+
**List Indexes:**
|
|
1078
|
+
|
|
1079
|
+
```javascript
|
|
1080
|
+
async function listIndexes() {
|
|
1081
|
+
try {
|
|
1082
|
+
await client.connect();
|
|
1083
|
+
const database = client.db('sample_db');
|
|
1084
|
+
const collection = database.collection('users');
|
|
1085
|
+
|
|
1086
|
+
const indexes = await collection.listIndexes().toArray();
|
|
1087
|
+
console.log('Indexes:', indexes);
|
|
1088
|
+
|
|
1089
|
+
} finally {
|
|
1090
|
+
await client.close();
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
listIndexes().catch(console.error);
|
|
1095
|
+
```
|
|
1096
|
+
|
|
1097
|
+
**Drop Index:**
|
|
1098
|
+
|
|
1099
|
+
```javascript
|
|
1100
|
+
async function dropIndex() {
|
|
1101
|
+
try {
|
|
1102
|
+
await client.connect();
|
|
1103
|
+
const database = client.db('sample_db');
|
|
1104
|
+
const collection = database.collection('users');
|
|
1105
|
+
|
|
1106
|
+
const result = await collection.dropIndex('email_1');
|
|
1107
|
+
console.log('Index dropped:', result);
|
|
1108
|
+
|
|
1109
|
+
} finally {
|
|
1110
|
+
await client.close();
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
dropIndex().catch(console.error);
|
|
1115
|
+
```
|
|
1116
|
+
|
|
1117
|
+
## Bulk Write Operations
|
|
1118
|
+
|
|
1119
|
+
**Bulk Write with Mixed Operations:**
|
|
1120
|
+
|
|
1121
|
+
```javascript
|
|
1122
|
+
async function bulkWrite() {
|
|
1123
|
+
try {
|
|
1124
|
+
await client.connect();
|
|
1125
|
+
const database = client.db('sample_db');
|
|
1126
|
+
const collection = database.collection('users');
|
|
1127
|
+
|
|
1128
|
+
const operations = [
|
|
1129
|
+
{
|
|
1130
|
+
insertOne: {
|
|
1131
|
+
document: { name: 'User 1', email: 'user1@example.com' }
|
|
1132
|
+
}
|
|
1133
|
+
},
|
|
1134
|
+
{
|
|
1135
|
+
updateOne: {
|
|
1136
|
+
filter: { email: 'john@example.com' },
|
|
1137
|
+
update: { $set: { status: 'active' } }
|
|
1138
|
+
}
|
|
1139
|
+
},
|
|
1140
|
+
{
|
|
1141
|
+
updateMany: {
|
|
1142
|
+
filter: { age: { $lt: 25 } },
|
|
1143
|
+
update: { $set: { category: 'young' } }
|
|
1144
|
+
}
|
|
1145
|
+
},
|
|
1146
|
+
{
|
|
1147
|
+
deleteOne: {
|
|
1148
|
+
filter: { email: 'old@example.com' }
|
|
1149
|
+
}
|
|
1150
|
+
},
|
|
1151
|
+
{
|
|
1152
|
+
replaceOne: {
|
|
1153
|
+
filter: { email: 'replace@example.com' },
|
|
1154
|
+
replacement: { name: 'Replaced', email: 'replace@example.com', age: 40 }
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
];
|
|
1158
|
+
|
|
1159
|
+
const result = await collection.bulkWrite(operations);
|
|
1160
|
+
|
|
1161
|
+
console.log(`${result.insertedCount} documents inserted`);
|
|
1162
|
+
console.log(`${result.modifiedCount} documents modified`);
|
|
1163
|
+
console.log(`${result.deletedCount} documents deleted`);
|
|
1164
|
+
console.log(`${result.upsertedCount} documents upserted`);
|
|
1165
|
+
|
|
1166
|
+
} finally {
|
|
1167
|
+
await client.close();
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
bulkWrite().catch(console.error);
|
|
1172
|
+
```
|
|
1173
|
+
|
|
1174
|
+
**Ordered vs Unordered Bulk Write:**
|
|
1175
|
+
|
|
1176
|
+
```javascript
|
|
1177
|
+
async function orderedVsUnorderedBulk() {
|
|
1178
|
+
try {
|
|
1179
|
+
await client.connect();
|
|
1180
|
+
const database = client.db('sample_db');
|
|
1181
|
+
const collection = database.collection('users');
|
|
1182
|
+
|
|
1183
|
+
const operations = [
|
|
1184
|
+
{ insertOne: { document: { name: 'User A' } } },
|
|
1185
|
+
{ insertOne: { document: { name: 'User B' } } }
|
|
1186
|
+
];
|
|
1187
|
+
|
|
1188
|
+
// Ordered (default): stops on first error
|
|
1189
|
+
const orderedResult = await collection.bulkWrite(operations, { ordered: true });
|
|
1190
|
+
|
|
1191
|
+
// Unordered: continues on errors, may execute in parallel
|
|
1192
|
+
const unorderedResult = await collection.bulkWrite(operations, { ordered: false });
|
|
1193
|
+
|
|
1194
|
+
console.log('Ordered result:', orderedResult);
|
|
1195
|
+
console.log('Unordered result:', unorderedResult);
|
|
1196
|
+
|
|
1197
|
+
} finally {
|
|
1198
|
+
await client.close();
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
orderedVsUnorderedBulk().catch(console.error);
|
|
1203
|
+
```
|
|
1204
|
+
|
|
1205
|
+
## Transactions
|
|
1206
|
+
|
|
1207
|
+
**Transaction with Session (Convenient API):**
|
|
1208
|
+
|
|
1209
|
+
```javascript
|
|
1210
|
+
async function transactionExample() {
|
|
1211
|
+
const session = client.startSession();
|
|
1212
|
+
|
|
1213
|
+
try {
|
|
1214
|
+
await client.connect();
|
|
1215
|
+
const database = client.db('sample_db');
|
|
1216
|
+
|
|
1217
|
+
const result = await session.withTransaction(async () => {
|
|
1218
|
+
const accounts = database.collection('accounts');
|
|
1219
|
+
const transactions = database.collection('transactions');
|
|
1220
|
+
|
|
1221
|
+
// Deduct from account A
|
|
1222
|
+
await accounts.updateOne(
|
|
1223
|
+
{ accountId: 'A' },
|
|
1224
|
+
{ $inc: { balance: -100 } },
|
|
1225
|
+
{ session }
|
|
1226
|
+
);
|
|
1227
|
+
|
|
1228
|
+
// Add to account B
|
|
1229
|
+
await accounts.updateOne(
|
|
1230
|
+
{ accountId: 'B' },
|
|
1231
|
+
{ $inc: { balance: 100 } },
|
|
1232
|
+
{ session }
|
|
1233
|
+
);
|
|
1234
|
+
|
|
1235
|
+
// Record transaction
|
|
1236
|
+
await transactions.insertOne(
|
|
1237
|
+
{
|
|
1238
|
+
from: 'A',
|
|
1239
|
+
to: 'B',
|
|
1240
|
+
amount: 100,
|
|
1241
|
+
timestamp: new Date()
|
|
1242
|
+
},
|
|
1243
|
+
{ session }
|
|
1244
|
+
);
|
|
1245
|
+
|
|
1246
|
+
return 'Transaction completed';
|
|
1247
|
+
});
|
|
1248
|
+
|
|
1249
|
+
console.log(result);
|
|
1250
|
+
|
|
1251
|
+
} finally {
|
|
1252
|
+
await session.endSession();
|
|
1253
|
+
await client.close();
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
transactionExample().catch(console.error);
|
|
1258
|
+
```
|
|
1259
|
+
|
|
1260
|
+
**Transaction with Core API (Manual Control):**
|
|
1261
|
+
|
|
1262
|
+
```javascript
|
|
1263
|
+
async function manualTransaction() {
|
|
1264
|
+
const session = client.startSession();
|
|
1265
|
+
|
|
1266
|
+
try {
|
|
1267
|
+
await client.connect();
|
|
1268
|
+
const database = client.db('sample_db');
|
|
1269
|
+
const accounts = database.collection('accounts');
|
|
1270
|
+
|
|
1271
|
+
// Start transaction
|
|
1272
|
+
session.startTransaction({
|
|
1273
|
+
readConcern: { level: 'snapshot' },
|
|
1274
|
+
writeConcern: { w: 'majority' }
|
|
1275
|
+
});
|
|
1276
|
+
|
|
1277
|
+
try {
|
|
1278
|
+
// Perform operations within transaction
|
|
1279
|
+
await accounts.updateOne(
|
|
1280
|
+
{ accountId: 'A' },
|
|
1281
|
+
{ $inc: { balance: -100 } },
|
|
1282
|
+
{ session }
|
|
1283
|
+
);
|
|
1284
|
+
|
|
1285
|
+
await accounts.updateOne(
|
|
1286
|
+
{ accountId: 'B' },
|
|
1287
|
+
{ $inc: { balance: 100 } },
|
|
1288
|
+
{ session }
|
|
1289
|
+
);
|
|
1290
|
+
|
|
1291
|
+
// Commit transaction
|
|
1292
|
+
await session.commitTransaction();
|
|
1293
|
+
console.log('Transaction committed');
|
|
1294
|
+
|
|
1295
|
+
} catch (error) {
|
|
1296
|
+
// Abort transaction on error
|
|
1297
|
+
await session.abortTransaction();
|
|
1298
|
+
console.error('Transaction aborted:', error);
|
|
1299
|
+
throw error;
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
} finally {
|
|
1303
|
+
await session.endSession();
|
|
1304
|
+
await client.close();
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
manualTransaction().catch(console.error);
|
|
1309
|
+
```
|
|
1310
|
+
|
|
1311
|
+
**Transaction with Retry Logic:**
|
|
1312
|
+
|
|
1313
|
+
```javascript
|
|
1314
|
+
async function transactionWithRetry() {
|
|
1315
|
+
const session = client.startSession();
|
|
1316
|
+
|
|
1317
|
+
async function runTransactionWithRetry(txnFunc, session) {
|
|
1318
|
+
while (true) {
|
|
1319
|
+
try {
|
|
1320
|
+
return await txnFunc(session);
|
|
1321
|
+
} catch (error) {
|
|
1322
|
+
if (error.hasErrorLabel('TransientTransactionError')) {
|
|
1323
|
+
console.log('TransientTransactionError, retrying transaction...');
|
|
1324
|
+
continue;
|
|
1325
|
+
}
|
|
1326
|
+
throw error;
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
async function commitWithRetry(session) {
|
|
1332
|
+
while (true) {
|
|
1333
|
+
try {
|
|
1334
|
+
await session.commitTransaction();
|
|
1335
|
+
console.log('Transaction committed');
|
|
1336
|
+
break;
|
|
1337
|
+
} catch (error) {
|
|
1338
|
+
if (error.hasErrorLabel('UnknownTransactionCommitResult')) {
|
|
1339
|
+
console.log('UnknownTransactionCommitResult, retrying commit...');
|
|
1340
|
+
continue;
|
|
1341
|
+
}
|
|
1342
|
+
throw error;
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
try {
|
|
1348
|
+
await client.connect();
|
|
1349
|
+
const database = client.db('sample_db');
|
|
1350
|
+
|
|
1351
|
+
await runTransactionWithRetry(async (session) => {
|
|
1352
|
+
session.startTransaction();
|
|
1353
|
+
|
|
1354
|
+
const accounts = database.collection('accounts');
|
|
1355
|
+
|
|
1356
|
+
await accounts.updateOne(
|
|
1357
|
+
{ accountId: 'A' },
|
|
1358
|
+
{ $inc: { balance: -50 } },
|
|
1359
|
+
{ session }
|
|
1360
|
+
);
|
|
1361
|
+
|
|
1362
|
+
await accounts.updateOne(
|
|
1363
|
+
{ accountId: 'B' },
|
|
1364
|
+
{ $inc: { balance: 50 } },
|
|
1365
|
+
{ session }
|
|
1366
|
+
);
|
|
1367
|
+
|
|
1368
|
+
await commitWithRetry(session);
|
|
1369
|
+
}, session);
|
|
1370
|
+
|
|
1371
|
+
} finally {
|
|
1372
|
+
await session.endSession();
|
|
1373
|
+
await client.close();
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
transactionWithRetry().catch(console.error);
|
|
1378
|
+
```
|
|
1379
|
+
|
|
1380
|
+
## Change Streams
|
|
1381
|
+
|
|
1382
|
+
**Watch Collection for Changes:**
|
|
1383
|
+
|
|
1384
|
+
```javascript
|
|
1385
|
+
async function watchCollection() {
|
|
1386
|
+
try {
|
|
1387
|
+
await client.connect();
|
|
1388
|
+
const database = client.db('sample_db');
|
|
1389
|
+
const collection = database.collection('users');
|
|
1390
|
+
|
|
1391
|
+
const changeStream = collection.watch();
|
|
1392
|
+
|
|
1393
|
+
console.log('Watching for changes...');
|
|
1394
|
+
|
|
1395
|
+
changeStream.on('change', (change) => {
|
|
1396
|
+
console.log('Change detected:', change);
|
|
1397
|
+
});
|
|
1398
|
+
|
|
1399
|
+
changeStream.on('error', (error) => {
|
|
1400
|
+
console.error('Change stream error:', error);
|
|
1401
|
+
});
|
|
1402
|
+
|
|
1403
|
+
// Keep the connection open
|
|
1404
|
+
// In production, you'd handle this differently
|
|
1405
|
+
|
|
1406
|
+
} catch (error) {
|
|
1407
|
+
console.error(error);
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
watchCollection().catch(console.error);
|
|
1412
|
+
```
|
|
1413
|
+
|
|
1414
|
+
**Watch with Filter Pipeline:**
|
|
1415
|
+
|
|
1416
|
+
```javascript
|
|
1417
|
+
async function watchWithFilter() {
|
|
1418
|
+
try {
|
|
1419
|
+
await client.connect();
|
|
1420
|
+
const database = client.db('sample_db');
|
|
1421
|
+
const collection = database.collection('users');
|
|
1422
|
+
|
|
1423
|
+
const pipeline = [
|
|
1424
|
+
{
|
|
1425
|
+
$match: {
|
|
1426
|
+
'operationType': { $in: ['insert', 'update'] },
|
|
1427
|
+
'fullDocument.age': { $gte: 18 }
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
];
|
|
1431
|
+
|
|
1432
|
+
const changeStream = collection.watch(pipeline);
|
|
1433
|
+
|
|
1434
|
+
console.log('Watching for adult user changes...');
|
|
1435
|
+
|
|
1436
|
+
for await (const change of changeStream) {
|
|
1437
|
+
console.log('Change:', change);
|
|
1438
|
+
|
|
1439
|
+
if (change.operationType === 'insert') {
|
|
1440
|
+
console.log('New user inserted:', change.fullDocument);
|
|
1441
|
+
} else if (change.operationType === 'update') {
|
|
1442
|
+
console.log('User updated:', change.documentKey);
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
} catch (error) {
|
|
1447
|
+
console.error(error);
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
watchWithFilter().catch(console.error);
|
|
1452
|
+
```
|
|
1453
|
+
|
|
1454
|
+
**Watch Database for Changes:**
|
|
1455
|
+
|
|
1456
|
+
```javascript
|
|
1457
|
+
async function watchDatabase() {
|
|
1458
|
+
try {
|
|
1459
|
+
await client.connect();
|
|
1460
|
+
const database = client.db('sample_db');
|
|
1461
|
+
|
|
1462
|
+
const changeStream = database.watch();
|
|
1463
|
+
|
|
1464
|
+
console.log('Watching database for changes...');
|
|
1465
|
+
|
|
1466
|
+
changeStream.on('change', (change) => {
|
|
1467
|
+
console.log(`Change in collection ${change.ns.coll}:`, change);
|
|
1468
|
+
});
|
|
1469
|
+
|
|
1470
|
+
} catch (error) {
|
|
1471
|
+
console.error(error);
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
watchDatabase().catch(console.error);
|
|
1476
|
+
```
|
|
1477
|
+
|
|
1478
|
+
## ObjectId Utilities
|
|
1479
|
+
|
|
1480
|
+
**Working with ObjectId:**
|
|
1481
|
+
|
|
1482
|
+
```javascript
|
|
1483
|
+
import { ObjectId } from 'mongodb';
|
|
1484
|
+
|
|
1485
|
+
async function objectIdExamples() {
|
|
1486
|
+
try {
|
|
1487
|
+
await client.connect();
|
|
1488
|
+
const database = client.db('sample_db');
|
|
1489
|
+
const collection = database.collection('users');
|
|
1490
|
+
|
|
1491
|
+
// Generate new ObjectId
|
|
1492
|
+
const newId = new ObjectId();
|
|
1493
|
+
console.log('New ObjectId:', newId.toString());
|
|
1494
|
+
|
|
1495
|
+
// Insert with custom ObjectId
|
|
1496
|
+
await collection.insertOne({
|
|
1497
|
+
_id: new ObjectId(),
|
|
1498
|
+
name: 'User with custom ID'
|
|
1499
|
+
});
|
|
1500
|
+
|
|
1501
|
+
// Find by ObjectId string
|
|
1502
|
+
const userId = '507f1f77bcf86cd799439011';
|
|
1503
|
+
const user = await collection.findOne({
|
|
1504
|
+
_id: new ObjectId(userId)
|
|
1505
|
+
});
|
|
1506
|
+
|
|
1507
|
+
// Get timestamp from ObjectId
|
|
1508
|
+
if (user) {
|
|
1509
|
+
const timestamp = user._id.getTimestamp();
|
|
1510
|
+
console.log('Document created at:', timestamp);
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
// Validate ObjectId
|
|
1514
|
+
const isValid = ObjectId.isValid('507f1f77bcf86cd799439011');
|
|
1515
|
+
console.log('Is valid ObjectId:', isValid);
|
|
1516
|
+
|
|
1517
|
+
} finally {
|
|
1518
|
+
await client.close();
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
objectIdExamples().catch(console.error);
|
|
1523
|
+
```
|
|
1524
|
+
|
|
1525
|
+
## Error Handling
|
|
1526
|
+
|
|
1527
|
+
**Comprehensive Error Handling:**
|
|
1528
|
+
|
|
1529
|
+
```javascript
|
|
1530
|
+
import { MongoClient, MongoServerError } from 'mongodb';
|
|
1531
|
+
|
|
1532
|
+
async function errorHandlingExample() {
|
|
1533
|
+
const client = new MongoClient(process.env.MONGODB_URI);
|
|
1534
|
+
|
|
1535
|
+
try {
|
|
1536
|
+
await client.connect();
|
|
1537
|
+
const database = client.db('sample_db');
|
|
1538
|
+
const collection = database.collection('users');
|
|
1539
|
+
|
|
1540
|
+
// Attempt operation
|
|
1541
|
+
await collection.insertOne({
|
|
1542
|
+
email: 'duplicate@example.com'
|
|
1543
|
+
});
|
|
1544
|
+
|
|
1545
|
+
} catch (error) {
|
|
1546
|
+
if (error instanceof MongoServerError) {
|
|
1547
|
+
switch (error.code) {
|
|
1548
|
+
case 11000:
|
|
1549
|
+
console.error('Duplicate key error:', error.message);
|
|
1550
|
+
break;
|
|
1551
|
+
case 121:
|
|
1552
|
+
console.error('Document validation failed:', error.message);
|
|
1553
|
+
break;
|
|
1554
|
+
default:
|
|
1555
|
+
console.error('MongoDB server error:', error.message);
|
|
1556
|
+
}
|
|
1557
|
+
} else if (error.name === 'MongoNetworkError') {
|
|
1558
|
+
console.error('Network error - cannot connect to MongoDB:', error.message);
|
|
1559
|
+
} else if (error.name === 'MongoParseError') {
|
|
1560
|
+
console.error('Invalid connection string:', error.message);
|
|
1561
|
+
} else {
|
|
1562
|
+
console.error('Unexpected error:', error);
|
|
1563
|
+
}
|
|
1564
|
+
} finally {
|
|
1565
|
+
await client.close();
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
errorHandlingExample().catch(console.error);
|
|
1570
|
+
```
|
|
1571
|
+
|
|
1572
|
+
**Retry Logic for Transient Errors:**
|
|
1573
|
+
|
|
1574
|
+
```javascript
|
|
1575
|
+
async function retryOperation(operation, maxRetries = 3) {
|
|
1576
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
1577
|
+
try {
|
|
1578
|
+
return await operation();
|
|
1579
|
+
} catch (error) {
|
|
1580
|
+
if (attempt === maxRetries) {
|
|
1581
|
+
throw error;
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
const isRetryable =
|
|
1585
|
+
error.name === 'MongoNetworkError' ||
|
|
1586
|
+
error.code === 'ETIMEDOUT' ||
|
|
1587
|
+
error.code === 'ECONNRESET';
|
|
1588
|
+
|
|
1589
|
+
if (!isRetryable) {
|
|
1590
|
+
throw error;
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1593
|
+
const delay = Math.pow(2, attempt) * 1000;
|
|
1594
|
+
console.log(`Attempt ${attempt} failed, retrying in ${delay}ms...`);
|
|
1595
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1600
|
+
async function useRetryLogic() {
|
|
1601
|
+
const client = new MongoClient(process.env.MONGODB_URI);
|
|
1602
|
+
|
|
1603
|
+
try {
|
|
1604
|
+
await retryOperation(async () => {
|
|
1605
|
+
await client.connect();
|
|
1606
|
+
const database = client.db('sample_db');
|
|
1607
|
+
const collection = database.collection('users');
|
|
1608
|
+
|
|
1609
|
+
return await collection.findOne({ email: 'test@example.com' });
|
|
1610
|
+
});
|
|
1611
|
+
|
|
1612
|
+
} finally {
|
|
1613
|
+
await client.close();
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
useRetryLogic().catch(console.error);
|
|
1618
|
+
```
|
|
1619
|
+
|
|
1620
|
+
## Query Operators
|
|
1621
|
+
|
|
1622
|
+
**Comparison Operators:**
|
|
1623
|
+
|
|
1624
|
+
```javascript
|
|
1625
|
+
async function comparisonOperators() {
|
|
1626
|
+
try {
|
|
1627
|
+
await client.connect();
|
|
1628
|
+
const database = client.db('sample_db');
|
|
1629
|
+
const collection = database.collection('products');
|
|
1630
|
+
|
|
1631
|
+
// $eq (equal)
|
|
1632
|
+
const equal = await collection.find({ price: { $eq: 99 } }).toArray();
|
|
1633
|
+
|
|
1634
|
+
// $ne (not equal)
|
|
1635
|
+
const notEqual = await collection.find({ status: { $ne: 'discontinued' } }).toArray();
|
|
1636
|
+
|
|
1637
|
+
// $gt, $gte (greater than, greater than or equal)
|
|
1638
|
+
const greaterThan = await collection.find({ price: { $gt: 50 } }).toArray();
|
|
1639
|
+
const greaterOrEqual = await collection.find({ stock: { $gte: 100 } }).toArray();
|
|
1640
|
+
|
|
1641
|
+
// $lt, $lte (less than, less than or equal)
|
|
1642
|
+
const lessThan = await collection.find({ price: { $lt: 100 } }).toArray();
|
|
1643
|
+
const lessOrEqual = await collection.find({ rating: { $lte: 3 } }).toArray();
|
|
1644
|
+
|
|
1645
|
+
// $in (in array)
|
|
1646
|
+
const inArray = await collection.find({
|
|
1647
|
+
category: { $in: ['electronics', 'computers'] }
|
|
1648
|
+
}).toArray();
|
|
1649
|
+
|
|
1650
|
+
// $nin (not in array)
|
|
1651
|
+
const notInArray = await collection.find({
|
|
1652
|
+
status: { $nin: ['discontinued', 'out-of-stock'] }
|
|
1653
|
+
}).toArray();
|
|
1654
|
+
|
|
1655
|
+
console.log('Query results:', equal, notEqual, greaterThan);
|
|
1656
|
+
|
|
1657
|
+
} finally {
|
|
1658
|
+
await client.close();
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
comparisonOperators().catch(console.error);
|
|
1663
|
+
```
|
|
1664
|
+
|
|
1665
|
+
**Logical Operators:**
|
|
1666
|
+
|
|
1667
|
+
```javascript
|
|
1668
|
+
async function logicalOperators() {
|
|
1669
|
+
try {
|
|
1670
|
+
await client.connect();
|
|
1671
|
+
const database = client.db('sample_db');
|
|
1672
|
+
const collection = database.collection('products');
|
|
1673
|
+
|
|
1674
|
+
// $and
|
|
1675
|
+
const andQuery = await collection.find({
|
|
1676
|
+
$and: [
|
|
1677
|
+
{ price: { $lt: 100 } },
|
|
1678
|
+
{ stock: { $gt: 0 } }
|
|
1679
|
+
]
|
|
1680
|
+
}).toArray();
|
|
1681
|
+
|
|
1682
|
+
// $or
|
|
1683
|
+
const orQuery = await collection.find({
|
|
1684
|
+
$or: [
|
|
1685
|
+
{ category: 'electronics' },
|
|
1686
|
+
{ featured: true }
|
|
1687
|
+
]
|
|
1688
|
+
}).toArray();
|
|
1689
|
+
|
|
1690
|
+
// $not
|
|
1691
|
+
const notQuery = await collection.find({
|
|
1692
|
+
price: { $not: { $gt: 100 } }
|
|
1693
|
+
}).toArray();
|
|
1694
|
+
|
|
1695
|
+
// $nor
|
|
1696
|
+
const norQuery = await collection.find({
|
|
1697
|
+
$nor: [
|
|
1698
|
+
{ status: 'discontinued' },
|
|
1699
|
+
{ stock: 0 }
|
|
1700
|
+
]
|
|
1701
|
+
}).toArray();
|
|
1702
|
+
|
|
1703
|
+
console.log('Logical query results:', andQuery.length, orQuery.length);
|
|
1704
|
+
|
|
1705
|
+
} finally {
|
|
1706
|
+
await client.close();
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
logicalOperators().catch(console.error);
|
|
1711
|
+
```
|
|
1712
|
+
|
|
1713
|
+
**Element Operators:**
|
|
1714
|
+
|
|
1715
|
+
```javascript
|
|
1716
|
+
async function elementOperators() {
|
|
1717
|
+
try {
|
|
1718
|
+
await client.connect();
|
|
1719
|
+
const database = client.db('sample_db');
|
|
1720
|
+
const collection = database.collection('users');
|
|
1721
|
+
|
|
1722
|
+
// $exists
|
|
1723
|
+
const hasPhone = await collection.find({
|
|
1724
|
+
phone: { $exists: true }
|
|
1725
|
+
}).toArray();
|
|
1726
|
+
|
|
1727
|
+
// $type
|
|
1728
|
+
const stringEmails = await collection.find({
|
|
1729
|
+
email: { $type: 'string' }
|
|
1730
|
+
}).toArray();
|
|
1731
|
+
|
|
1732
|
+
console.log('Element query results:', hasPhone.length, stringEmails.length);
|
|
1733
|
+
|
|
1734
|
+
} finally {
|
|
1735
|
+
await client.close();
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
elementOperators().catch(console.error);
|
|
1740
|
+
```
|
|
1741
|
+
|
|
1742
|
+
**Array Operators:**
|
|
1743
|
+
|
|
1744
|
+
```javascript
|
|
1745
|
+
async function arrayOperators() {
|
|
1746
|
+
try {
|
|
1747
|
+
await client.connect();
|
|
1748
|
+
const database = client.db('sample_db');
|
|
1749
|
+
const collection = database.collection('users');
|
|
1750
|
+
|
|
1751
|
+
// $all
|
|
1752
|
+
const allTags = await collection.find({
|
|
1753
|
+
tags: { $all: ['premium', 'verified'] }
|
|
1754
|
+
}).toArray();
|
|
1755
|
+
|
|
1756
|
+
// $elemMatch
|
|
1757
|
+
const elemMatch = await collection.find({
|
|
1758
|
+
scores: { $elemMatch: { $gte: 80, $lt: 90 } }
|
|
1759
|
+
}).toArray();
|
|
1760
|
+
|
|
1761
|
+
// $size
|
|
1762
|
+
const exactSize = await collection.find({
|
|
1763
|
+
tags: { $size: 3 }
|
|
1764
|
+
}).toArray();
|
|
1765
|
+
|
|
1766
|
+
console.log('Array query results:', allTags.length, elemMatch.length);
|
|
1767
|
+
|
|
1768
|
+
} finally {
|
|
1769
|
+
await client.close();
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1773
|
+
arrayOperators().catch(console.error);
|
|
1774
|
+
```
|
|
1775
|
+
|
|
1776
|
+
## Advanced Patterns
|
|
1777
|
+
|
|
1778
|
+
**Connection Pooling:**
|
|
1779
|
+
|
|
1780
|
+
```javascript
|
|
1781
|
+
import { MongoClient } from 'mongodb';
|
|
1782
|
+
|
|
1783
|
+
const uri = process.env.MONGODB_URI;
|
|
1784
|
+
|
|
1785
|
+
const client = new MongoClient(uri, {
|
|
1786
|
+
maxPoolSize: 50,
|
|
1787
|
+
minPoolSize: 10,
|
|
1788
|
+
maxIdleTimeMS: 30000,
|
|
1789
|
+
waitQueueTimeoutMS: 5000
|
|
1790
|
+
});
|
|
1791
|
+
|
|
1792
|
+
let isConnected = false;
|
|
1793
|
+
|
|
1794
|
+
async function getDatabase() {
|
|
1795
|
+
if (!isConnected) {
|
|
1796
|
+
await client.connect();
|
|
1797
|
+
isConnected = true;
|
|
1798
|
+
}
|
|
1799
|
+
return client.db('sample_db');
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1802
|
+
export { getDatabase, client };
|
|
1803
|
+
```
|
|
1804
|
+
|
|
1805
|
+
**Database and Collection Management:**
|
|
1806
|
+
|
|
1807
|
+
```javascript
|
|
1808
|
+
async function databaseManagement() {
|
|
1809
|
+
try {
|
|
1810
|
+
await client.connect();
|
|
1811
|
+
|
|
1812
|
+
// List databases
|
|
1813
|
+
const adminDb = client.db().admin();
|
|
1814
|
+
const dbList = await adminDb.listDatabases();
|
|
1815
|
+
console.log('Databases:', dbList.databases);
|
|
1816
|
+
|
|
1817
|
+
// List collections
|
|
1818
|
+
const database = client.db('sample_db');
|
|
1819
|
+
const collections = await database.listCollections().toArray();
|
|
1820
|
+
console.log('Collections:', collections);
|
|
1821
|
+
|
|
1822
|
+
// Create collection with options
|
|
1823
|
+
await database.createCollection('newCollection', {
|
|
1824
|
+
validator: {
|
|
1825
|
+
$jsonSchema: {
|
|
1826
|
+
bsonType: 'object',
|
|
1827
|
+
required: ['name', 'email'],
|
|
1828
|
+
properties: {
|
|
1829
|
+
name: {
|
|
1830
|
+
bsonType: 'string',
|
|
1831
|
+
description: 'must be a string and is required'
|
|
1832
|
+
},
|
|
1833
|
+
email: {
|
|
1834
|
+
bsonType: 'string',
|
|
1835
|
+
pattern: '^.+@.+$',
|
|
1836
|
+
description: 'must be a valid email'
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
});
|
|
1842
|
+
|
|
1843
|
+
// Drop collection
|
|
1844
|
+
// await database.collection('oldCollection').drop();
|
|
1845
|
+
|
|
1846
|
+
} finally {
|
|
1847
|
+
await client.close();
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
databaseManagement().catch(console.error);
|
|
1852
|
+
```
|
|
1853
|
+
|
|
1854
|
+
**Schema Validation:**
|
|
1855
|
+
|
|
1856
|
+
```javascript
|
|
1857
|
+
async function addSchemaValidation() {
|
|
1858
|
+
try {
|
|
1859
|
+
await client.connect();
|
|
1860
|
+
const database = client.db('sample_db');
|
|
1861
|
+
|
|
1862
|
+
await database.command({
|
|
1863
|
+
collMod: 'users',
|
|
1864
|
+
validator: {
|
|
1865
|
+
$jsonSchema: {
|
|
1866
|
+
bsonType: 'object',
|
|
1867
|
+
required: ['name', 'email', 'age'],
|
|
1868
|
+
properties: {
|
|
1869
|
+
name: {
|
|
1870
|
+
bsonType: 'string',
|
|
1871
|
+
description: 'must be a string and is required'
|
|
1872
|
+
},
|
|
1873
|
+
email: {
|
|
1874
|
+
bsonType: 'string',
|
|
1875
|
+
pattern: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$',
|
|
1876
|
+
description: 'must be a valid email and is required'
|
|
1877
|
+
},
|
|
1878
|
+
age: {
|
|
1879
|
+
bsonType: 'int',
|
|
1880
|
+
minimum: 0,
|
|
1881
|
+
maximum: 150,
|
|
1882
|
+
description: 'must be an integer between 0 and 150'
|
|
1883
|
+
},
|
|
1884
|
+
status: {
|
|
1885
|
+
enum: ['active', 'inactive', 'suspended'],
|
|
1886
|
+
description: 'can only be one of the enum values'
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
},
|
|
1891
|
+
validationLevel: 'moderate',
|
|
1892
|
+
validationAction: 'error'
|
|
1893
|
+
});
|
|
1894
|
+
|
|
1895
|
+
console.log('Schema validation added');
|
|
1896
|
+
|
|
1897
|
+
} finally {
|
|
1898
|
+
await client.close();
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
addSchemaValidation().catch(console.error);
|
|
1903
|
+
```
|
|
1904
|
+
|
|
1905
|
+
**Time Series Collections:**
|
|
1906
|
+
|
|
1907
|
+
```javascript
|
|
1908
|
+
async function createTimeSeriesCollection() {
|
|
1909
|
+
try {
|
|
1910
|
+
await client.connect();
|
|
1911
|
+
const database = client.db('sample_db');
|
|
1912
|
+
|
|
1913
|
+
await database.createCollection('sensor_data', {
|
|
1914
|
+
timeseries: {
|
|
1915
|
+
timeField: 'timestamp',
|
|
1916
|
+
metaField: 'sensorId',
|
|
1917
|
+
granularity: 'seconds'
|
|
1918
|
+
}
|
|
1919
|
+
});
|
|
1920
|
+
|
|
1921
|
+
const collection = database.collection('sensor_data');
|
|
1922
|
+
|
|
1923
|
+
// Insert time series data
|
|
1924
|
+
await collection.insertMany([
|
|
1925
|
+
{
|
|
1926
|
+
sensorId: 'sensor1',
|
|
1927
|
+
timestamp: new Date('2024-01-01T00:00:00Z'),
|
|
1928
|
+
temperature: 22.5,
|
|
1929
|
+
humidity: 60
|
|
1930
|
+
},
|
|
1931
|
+
{
|
|
1932
|
+
sensorId: 'sensor1',
|
|
1933
|
+
timestamp: new Date('2024-01-01T00:01:00Z'),
|
|
1934
|
+
temperature: 22.7,
|
|
1935
|
+
humidity: 59
|
|
1936
|
+
}
|
|
1937
|
+
]);
|
|
1938
|
+
|
|
1939
|
+
console.log('Time series data inserted');
|
|
1940
|
+
|
|
1941
|
+
} finally {
|
|
1942
|
+
await client.close();
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1946
|
+
createTimeSeriesCollection().catch(console.error);
|
|
1947
|
+
```
|
|
1948
|
+
|
|
1949
|
+
**Read and Write Concerns:**
|
|
1950
|
+
|
|
1951
|
+
```javascript
|
|
1952
|
+
async function readWriteConcerns() {
|
|
1953
|
+
try {
|
|
1954
|
+
await client.connect();
|
|
1955
|
+
const database = client.db('sample_db');
|
|
1956
|
+
const collection = database.collection('users');
|
|
1957
|
+
|
|
1958
|
+
// Write concern
|
|
1959
|
+
const insertResult = await collection.insertOne(
|
|
1960
|
+
{ name: 'John', email: 'john@example.com' },
|
|
1961
|
+
{
|
|
1962
|
+
writeConcern: {
|
|
1963
|
+
w: 'majority',
|
|
1964
|
+
j: true,
|
|
1965
|
+
wtimeout: 5000
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
);
|
|
1969
|
+
|
|
1970
|
+
// Read concern
|
|
1971
|
+
const findResult = await collection.findOne(
|
|
1972
|
+
{ email: 'john@example.com' },
|
|
1973
|
+
{
|
|
1974
|
+
readConcern: { level: 'majority' }
|
|
1975
|
+
}
|
|
1976
|
+
);
|
|
1977
|
+
|
|
1978
|
+
console.log('Insert result:', insertResult);
|
|
1979
|
+
console.log('Find result:', findResult);
|
|
1980
|
+
|
|
1981
|
+
} finally {
|
|
1982
|
+
await client.close();
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
|
|
1986
|
+
readWriteConcerns().catch(console.error);
|
|
1987
|
+
```
|
|
1988
|
+
|
|
1989
|
+
**Count Documents:**
|
|
1990
|
+
|
|
1991
|
+
```javascript
|
|
1992
|
+
async function countExamples() {
|
|
1993
|
+
try {
|
|
1994
|
+
await client.connect();
|
|
1995
|
+
const database = client.db('sample_db');
|
|
1996
|
+
const collection = database.collection('users');
|
|
1997
|
+
|
|
1998
|
+
// Count all documents
|
|
1999
|
+
const totalCount = await collection.countDocuments({});
|
|
2000
|
+
console.log('Total documents:', totalCount);
|
|
2001
|
+
|
|
2002
|
+
// Count with filter
|
|
2003
|
+
const activeCount = await collection.countDocuments({ status: 'active' });
|
|
2004
|
+
console.log('Active users:', activeCount);
|
|
2005
|
+
|
|
2006
|
+
// Estimated count (faster but less accurate)
|
|
2007
|
+
const estimatedCount = await collection.estimatedDocumentCount();
|
|
2008
|
+
console.log('Estimated count:', estimatedCount);
|
|
2009
|
+
|
|
2010
|
+
} finally {
|
|
2011
|
+
await client.close();
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
countExamples().catch(console.error);
|
|
2016
|
+
```
|
|
2017
|
+
|
|
2018
|
+
**Distinct Values:**
|
|
2019
|
+
|
|
2020
|
+
```javascript
|
|
2021
|
+
async function distinctValues() {
|
|
2022
|
+
try {
|
|
2023
|
+
await client.connect();
|
|
2024
|
+
const database = client.db('sample_db');
|
|
2025
|
+
const collection = database.collection('users');
|
|
2026
|
+
|
|
2027
|
+
// Get distinct values
|
|
2028
|
+
const cities = await collection.distinct('city');
|
|
2029
|
+
console.log('Distinct cities:', cities);
|
|
2030
|
+
|
|
2031
|
+
// Get distinct values with filter
|
|
2032
|
+
const activeCities = await collection.distinct('city', { status: 'active' });
|
|
2033
|
+
console.log('Cities with active users:', activeCities);
|
|
2034
|
+
|
|
2035
|
+
} finally {
|
|
2036
|
+
await client.close();
|
|
2037
|
+
}
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
distinctValues().catch(console.error);
|
|
2041
|
+
```
|