or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

asyncio-operations.mdchange-streams.mdclient-encryption.mdcursor-operations.mdgridfs-operations.mdindex.mdtornado-operations.mdweb-integration.md

index.mddocs/

0

# Motor

1

2

A full-featured, non-blocking MongoDB driver for Python asyncio and Tornado applications. Motor provides a coroutine-based API for non-blocking access to MongoDB, enabling high-throughput database operations in asynchronous Python applications.

3

4

## Package Information

5

6

- **Package Name**: motor

7

- **Language**: Python

8

- **Installation**: `pip install motor`

9

- **License**: Apache License 2.0

10

- **Documentation**: https://motor.readthedocs.io/en/stable/

11

12

## Core Imports

13

14

For asyncio applications:

15

16

```python

17

import motor.motor_asyncio as motor

18

```

19

20

For Tornado applications:

21

22

```python

23

import motor.motor_tornado as motor

24

```

25

26

Specific imports:

27

28

```python

29

from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorDatabase, AsyncIOMotorCollection

30

from motor.motor_tornado import MotorClient, MotorDatabase, MotorCollection

31

```

32

33

## Basic Usage

34

35

### AsyncIO Example

36

37

```python

38

import asyncio

39

import motor.motor_asyncio

40

41

async def main():

42

# Connect to MongoDB

43

client = motor.motor_asyncio.AsyncIOMotorClient('mongodb://localhost:27017')

44

45

# Get database and collection

46

db = client.my_database

47

collection = db.my_collection

48

49

# Insert a document

50

result = await collection.insert_one({'name': 'Alice', 'age': 30})

51

print(f"Inserted document with ID: {result.inserted_id}")

52

53

# Find documents

54

async for document in collection.find({'age': {'$gte': 18}}):

55

print(document)

56

57

# Find one document

58

user = await collection.find_one({'name': 'Alice'})

59

print(f"Found user: {user}")

60

61

# Update a document

62

await collection.update_one(

63

{'name': 'Alice'},

64

{'$set': {'age': 31}}

65

)

66

67

# Delete a document

68

await collection.delete_one({'name': 'Alice'})

69

70

# Close the connection

71

client.close()

72

73

asyncio.run(main())

74

```

75

76

### Tornado Example

77

78

```python

79

import tornado.ioloop

80

import motor.motor_tornado

81

82

def main():

83

client = motor.motor_tornado.MotorClient('mongodb://localhost:27017')

84

db = client.my_database

85

collection = db.my_collection

86

87

# Insert and handle with callback

88

future = collection.insert_one({'name': 'Bob', 'age': 25})

89

tornado.ioloop.IOLoop.current().run_sync(lambda: future)

90

91

client.close()

92

93

if __name__ == '__main__':

94

main()

95

```

96

97

## Architecture

98

99

Motor uses a sophisticated metaprogramming system to create framework-specific classes from framework-agnostic base classes:

100

101

- **Framework-Agnostic Core**: Base classes in `motor.core` define all MongoDB operations

102

- **Framework-Specific Wrappers**: Classes in `motor_asyncio` and `motor_tornado` adapt the core for each framework

103

- **Metaprogramming Decorators**: Transform synchronous PyMongo operations into asynchronous Motor operations

104

- **Dual API Support**: Complete API compatibility with both asyncio and Tornado frameworks

105

106

This design enables Motor to provide identical functionality for both asyncio and Tornado while maintaining a single codebase for core MongoDB operations.

107

108

## Capabilities

109

110

### AsyncIO Client Operations

111

112

Core MongoDB client, database, and collection operations optimized for Python's asyncio framework. Supports async/await syntax and native asyncio.Future objects.

113

114

```python { .api }

115

class AsyncIOMotorClient:

116

def __init__(self, host='localhost', port=27017, **kwargs): ...

117

def get_database(self, name=None, **kwargs) -> AsyncIOMotorDatabase: ...

118

def get_default_database(self, **kwargs) -> AsyncIOMotorDatabase: ...

119

async def list_databases(self, session=None, **kwargs): ...

120

async def list_database_names(self, session=None, **kwargs) -> list[str]: ...

121

async def server_info(self) -> dict: ...

122

async def start_session(self, **kwargs): ...

123

def close(self) -> None: ...

124

125

class AsyncIOMotorDatabase:

126

def get_collection(self, name, **kwargs) -> AsyncIOMotorCollection: ...

127

async def create_collection(self, name, **kwargs) -> AsyncIOMotorCollection: ...

128

async def drop_collection(self, name_or_collection, **kwargs): ...

129

async def list_collection_names(self, **kwargs) -> list[str]: ...

130

async def command(self, command, **kwargs): ...

131

132

class AsyncIOMotorCollection:

133

async def insert_one(self, document, **kwargs): ...

134

async def insert_many(self, documents, **kwargs): ...

135

async def find_one(self, filter=None, **kwargs): ...

136

def find(self, filter=None, **kwargs) -> AsyncIOMotorCursor: ...

137

async def update_one(self, filter, update, **kwargs): ...

138

async def update_many(self, filter, update, **kwargs): ...

139

async def delete_one(self, filter, **kwargs): ...

140

async def delete_many(self, filter, **kwargs): ...

141

async def count_documents(self, filter, **kwargs) -> int: ...

142

143

class AsyncIOMotorClientSession:

144

async def start_transaction(self, **kwargs): ...

145

async def commit_transaction(self): ...

146

async def abort_transaction(self): ...

147

async def with_transaction(self, coro, **kwargs): ...

148

async def end_session(self): ...

149

async def __aenter__(self): ...

150

async def __aexit__(self, exc_type, exc_val, exc_tb): ...

151

```

152

153

[AsyncIO Operations](./asyncio-operations.md)

154

155

### Tornado Client Operations

156

157

Core MongoDB client, database, and collection operations optimized for Tornado's IOLoop and Future objects. Provides callback-based and Future-based async operations.

158

159

```python { .api }

160

class MotorClient:

161

def __init__(self, host='localhost', port=27017, **kwargs): ...

162

def get_database(self, name=None, **kwargs) -> MotorDatabase: ...

163

def get_default_database(self, **kwargs) -> MotorDatabase: ...

164

def list_databases(self, session=None, **kwargs) -> tornado.concurrent.Future: ...

165

def list_database_names(self, session=None, **kwargs) -> tornado.concurrent.Future: ...

166

def server_info(self) -> tornado.concurrent.Future: ...

167

def start_session(self, **kwargs) -> tornado.concurrent.Future: ...

168

def close(self) -> None: ...

169

170

class MotorDatabase:

171

def get_collection(self, name, **kwargs) -> MotorCollection: ...

172

def create_collection(self, name, **kwargs) -> tornado.concurrent.Future: ...

173

def drop_collection(self, name_or_collection, **kwargs) -> tornado.concurrent.Future: ...

174

def list_collection_names(self, **kwargs) -> tornado.concurrent.Future: ...

175

def command(self, command, **kwargs) -> tornado.concurrent.Future: ...

176

177

class MotorCollection:

178

def insert_one(self, document, **kwargs) -> tornado.concurrent.Future: ...

179

def insert_many(self, documents, **kwargs) -> tornado.concurrent.Future: ...

180

def find_one(self, filter=None, **kwargs) -> tornado.concurrent.Future: ...

181

def find(self, filter=None, **kwargs) -> MotorCursor: ...

182

def update_one(self, filter, update, **kwargs) -> tornado.concurrent.Future: ...

183

def update_many(self, filter, update, **kwargs) -> tornado.concurrent.Future: ...

184

def delete_one(self, filter, **kwargs) -> tornado.concurrent.Future: ...

185

def delete_many(self, filter, **kwargs) -> tornado.concurrent.Future: ...

186

def count_documents(self, filter, **kwargs) -> tornado.concurrent.Future: ...

187

188

class MotorClientSession:

189

def start_transaction(self, **kwargs): ...

190

def commit_transaction(self) -> tornado.concurrent.Future: ...

191

def abort_transaction(self) -> tornado.concurrent.Future: ...

192

def with_transaction(self, coro, **kwargs) -> tornado.concurrent.Future: ...

193

def end_session(self) -> tornado.concurrent.Future: ...

194

```

195

196

[Tornado Operations](./tornado-operations.md)

197

198

### GridFS File Storage

199

200

GridFS support for storing and retrieving large files in MongoDB. Provides streaming file operations for both asyncio and Tornado frameworks.

201

202

```python { .api }

203

class AsyncIOMotorGridFSBucket:

204

def __init__(self, database, bucket_name='fs', **kwargs): ...

205

async def upload_from_stream(self, filename, source, **kwargs): ...

206

async def upload_from_stream_with_id(self, file_id, filename, source, **kwargs): ...

207

async def open_download_stream(self, file_id, **kwargs) -> AsyncIOMotorGridOut: ...

208

async def open_download_stream_by_name(self, filename, **kwargs) -> AsyncIOMotorGridOut: ...

209

def open_upload_stream(self, filename, **kwargs) -> AsyncIOMotorGridIn: ...

210

def open_upload_stream_with_id(self, file_id, filename, **kwargs) -> AsyncIOMotorGridIn: ...

211

async def delete(self, file_id, **kwargs): ...

212

async def rename(self, file_id, new_filename, **kwargs): ...

213

214

class AsyncIOMotorGridOut:

215

# Properties

216

_id: Any

217

filename: str

218

length: int

219

content_type: str

220

upload_date: datetime.datetime

221

metadata: dict

222

223

# Methods

224

async def open(self): ...

225

async def read(self, size=-1) -> bytes: ...

226

async def readline(self, size=-1) -> bytes: ...

227

async def readchunk(self) -> bytes: ...

228

def seek(self, pos, whence=0) -> int: ...

229

def tell(self) -> int: ...

230

def close(self) -> None: ...

231

232

class AsyncIOMotorGridIn:

233

# Properties

234

_id: Any

235

filename: str

236

content_type: str

237

chunk_size: int

238

closed: bool

239

240

# Methods

241

async def write(self, data) -> None: ...

242

async def writelines(self, lines) -> None: ...

243

async def close(self) -> None: ...

244

async def abort(self) -> None: ...

245

```

246

247

[GridFS Operations](./gridfs-operations.md)

248

249

### Cursor Operations

250

251

Cursor functionality for iterating over query results, command results, and change streams. Supports both async iteration and traditional cursor methods.

252

253

```python { .api }

254

class AsyncIOMotorCursor:

255

def limit(self, limit) -> AsyncIOMotorCursor: ...

256

def skip(self, skip) -> AsyncIOMotorCursor: ...

257

def sort(self, key_or_list, direction=None) -> AsyncIOMotorCursor: ...

258

def batch_size(self, batch_size) -> AsyncIOMotorCursor: ...

259

async def to_list(self, length=None) -> list: ...

260

def __aiter__(self): ...

261

async def __anext__(self): ...

262

263

class AsyncIOMotorCommandCursor:

264

def batch_size(self, batch_size) -> AsyncIOMotorCommandCursor: ...

265

async def to_list(self, length=None) -> list: ...

266

def __aiter__(self): ...

267

async def __anext__(self): ...

268

269

class AsyncIOMotorLatentCommandCursor(AsyncIOMotorCommandCursor):

270

def batch_size(self, batch_size) -> AsyncIOMotorLatentCommandCursor: ...

271

async def to_list(self, length=None) -> list: ...

272

def __aiter__(self): ...

273

async def __anext__(self): ...

274

275

class AsyncIOMotorChangeStream:

276

async def next(self): ...

277

def __aiter__(self): ...

278

async def __anext__(self): ...

279

async def close(self): ...

280

def resume_token(self): ...

281

```

282

283

[Cursor Operations](./cursor-operations.md)

284

285

### Change Streams

286

287

Real-time change monitoring for watching database, collection, or document changes. Enables reactive applications that respond to data modifications.

288

289

```python { .api }

290

def watch(pipeline=None, **kwargs) -> AsyncIOMotorChangeStream: ...

291

292

class AsyncIOMotorChangeStream:

293

async def next(self): ...

294

def __aiter__(self): ...

295

async def __anext__(self): ...

296

async def close(self): ...

297

@property

298

def resume_token(self): ...

299

```

300

301

[Change Streams](./change-streams.md)

302

303

### Web Integration

304

305

HTTP handlers for serving GridFS files through web frameworks. Includes optimized handlers for both Tornado and aiohttp with support for HTTP caching, range requests, and content negotiation.

306

307

```python { .api }

308

# Tornado Integration

309

class GridFSHandler(tornado.web.RequestHandler):

310

def initialize(self, database, **kwargs): ...

311

async def get(self, filename, include_body=True): ...

312

async def head(self, filename): ...

313

314

# aiohttp Integration

315

class AIOHTTPGridFS:

316

def __init__(self, database, root_collection='fs', **kwargs): ...

317

async def __call__(self, request) -> aiohttp.web.Response: ...

318

319

def get_gridfs_file(bucket, filename, request): ...

320

def get_cache_time(filename, modified, mime_type) -> int: ...

321

def set_extra_headers(response, gridout) -> None: ...

322

```

323

324

[Web Integration](./web-integration.md)

325

326

### Client-Side Field Level Encryption

327

328

Encryption and decryption of fields for client-side field level encryption (CSFLE). Provides key management, field encryption/decryption, and secure data operations.

329

330

```python { .api }

331

class AsyncIOMotorClientEncryption:

332

def __init__(

333

self,

334

kms_providers: dict,

335

key_vault_namespace: str,

336

key_vault_client: AsyncIOMotorClient,

337

codec_options: CodecOptions,

338

**kwargs

339

): ...

340

async def create_data_key(

341

self,

342

kms_provider: str,

343

master_key: Optional[dict] = None,

344

key_alt_names: Optional[list] = None,

345

key_material: Optional[bytes] = None

346

) -> Binary: ...

347

async def encrypt(

348

self,

349

value: Any,

350

algorithm: str,

351

key_id: Optional[Binary] = None,

352

key_alt_name: Optional[str] = None,

353

**kwargs

354

) -> Binary: ...

355

async def decrypt(self, value: Binary) -> Any: ...

356

async def close(self) -> None: ...

357

```

358

359

[Client Encryption](./client-encryption.md)

360

361

## Common Patterns

362

363

### Connection Management

364

365

```python

366

# AsyncIO with connection pooling

367

client = motor.motor_asyncio.AsyncIOMotorClient(

368

'mongodb://localhost:27017',

369

maxPoolSize=10,

370

minPoolSize=5

371

)

372

373

# Always close connections

374

try:

375

# Your database operations

376

pass

377

finally:

378

client.close()

379

```

380

381

### Error Handling

382

383

```python

384

import pymongo.errors

385

386

try:

387

await collection.insert_one(document)

388

except pymongo.errors.DuplicateKeyError:

389

print("Document already exists")

390

except pymongo.errors.ConnectionFailure:

391

print("Failed to connect to MongoDB")

392

```

393

394

### Transaction Support

395

396

```python

397

async def run_in_transaction():

398

async with await client.start_session() as session:

399

async with session.start_transaction():

400

await collection1.insert_one(doc1, session=session)

401

await collection2.update_one(filter, update, session=session)

402

```

403

404

## Types

405

406

```python { .api }

407

from typing import Any, Optional, Union, Dict, List

408

from datetime import datetime

409

import tornado.concurrent

410

from pymongo.results import InsertOneResult, InsertManyResult, UpdateResult, DeleteResult

411

from bson import Binary, CodecOptions

412

413

# Common type aliases used throughout Motor

414

Document = Dict[str, Any]

415

Filter = Dict[str, Any]

416

Update = Dict[str, Any]

417

Pipeline = List[Dict[str, Any]]

418

419

class InsertOneResult:

420

inserted_id: Any

421

acknowledged: bool

422

423

class InsertManyResult:

424

inserted_ids: List[Any]

425

acknowledged: bool

426

427

class UpdateResult:

428

matched_count: int

429

modified_count: int

430

upserted_id: Optional[Any]

431

acknowledged: bool

432

433

class DeleteResult:

434

deleted_count: int

435

acknowledged: bool

436

```