MongoDB QuickStart
验证:未记录
- 适用版本
- 未记录
- 验证范围
- 尚未登记验证记录。
本文缩写(英文全称与中文含义)
| 缩写 | 英文全称/名称 | 中文含义 |
|---|---|---|
| API | Application Programming Interface | 应用程序编程接口 |
| BSON | Binary JSON | MongoDB 使用的二进制文档格式 |
| CLI | Command-Line Interface | 命令行接口 |
| COLLSCAN | Collection Scan | MongoDB 全集合扫描 |
| JSON | JavaScript Object Notation | 一种结构化数据格式 |
| MB | Megabyte | 十进制兆字节,1 MB = 10⁶ 字节 |
| QPS | Queries Per Second | 每秒查询数 |
| URI | Uniform Resource Identifier | 统一资源标识符 |
Links#
https://www.mongodb.com/docs/languages/java/
https://www.mongodb.com/docs/drivers/java/sync/current/getting-started/quick-reference/
https://www.mongodb.com/docs/drivers/java/sync/current/data-formats/document-data-format-pojo/
https://www.mongodb.com/docs/manual/reference/connection-string/
https://www.mongodb.com/docs/manual/crud/1. What You Need To Know#
MongoClient 应复用连接池,不要每个请求创建新 client;连接池上限要和应用副本数一起核算。
MongoDB concepts:
database:
类似 MySQL database
collection:
类似 table,但不要求每条 document schema 完全一致
document:
BSON document,类似 JSON object
一条 document 最大 16 MB
_id:
每条 document 的 primary key
不指定时 MongoDB 会自动生成 ObjectId
index:
query performance 的核心
没有合适 index,高 QPS query 很容易变成 COLLSCAN
replica set:
production baseline
primary handles writes
secondary replicates from primary
connection string:
driver 通过 URI 连接 MongoDB
production replica set 应该写多个 host + replicaSetmental model:
MongoClient
-> MongoDatabase
-> MongoCollection<Document>
-> insertOne / find / updateOne / deleteOne2. Hello World Goal#
we will build:
Java CLI app
connect to MongoDB
create collection index
insert one order
query order by user_id
update order status
delete order
language:
Java
driver:
MongoDB Java Sync Driver3. Maven Dependency#
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>me.xiezhao.demo</groupId>
<artifactId>mongodb-hello-world</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>5.5.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.5.0</version>
</plugin>
</plugins>
</build>
</project>4. Configuration#
local dev#
# application.properties
mongodb.uri=mongodb://root:change-me@localhost:27017/order?authSource=admin&appName=order-api
mongodb.database=order
mongodb.collection=ordersproduction replica set#
mongodb.uri=mongodb://order_app:<password>@mongo-1:27017,mongo-2:27017,mongo-3:27017/order?replicaSet=rs0&authSource=admin&appName=order-api&retryWrites=true&w=majority
mongodb.database=order
mongodb.collection=ordersimportant options:
replicaSet=rs0
tell driver this is a replica set
authSource=admin
user is created in admin database
appName=order-api
appears in MongoDB logs / profiler
retryWrites=true
driver can retry supported write operations
w=majority
write acknowledged by majority5. Start MongoDB Locally#
docker run -d --name mongo -p 27017:27017 -e MONGO_INITDB_ROOT_USERNAME=root -e MONGO_INITDB_ROOT_PASSWORD=change-me mongo:8mongosh "mongodb://root:change-me@localhost:27017/admin"6. Project Structure#
mongodb-hello-world
├── pom.xml
└── src
└── main
├── java
│ └── me
│ └── xiezhao
│ └── demo
│ └── MongoHelloWorld.java
└── resources
└── application.properties7. Java Hello World#
package me.xiezhao.demo;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Indexes;
import com.mongodb.client.model.Updates;
import org.bson.Document;
import org.bson.conversions.Bson;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.Properties;
public class MongoHelloWorld {
public static void main(String[] args) throws IOException {
Properties properties = loadProperties();
String uri = properties.getProperty("mongodb.uri");
String databaseName = properties.getProperty("mongodb.database");
String collectionName = properties.getProperty("mongodb.collection");
try (MongoClient client = MongoClients.create(uri)) {
MongoDatabase database = client.getDatabase(databaseName);
MongoCollection<Document> orders = database.getCollection(collectionName);
orders.createIndex(Indexes.compoundIndex(
Indexes.ascending("user_id"),
Indexes.descending("created_at")
));
String orderId = "o-1001";
String userId = "u-1001";
Document order = new Document("order_id", orderId)
.append("user_id", userId)
.append("status", "PENDING")
.append("amount", new BigDecimal("99.90"))
.append("created_at", Instant.now());
orders.insertOne(order);
Bson queryByUser = Filters.eq("user_id", userId);
Document found = orders.find(queryByUser)
.sort(Indexes.descending("created_at"))
.first();
System.out.println("found order: " + found.toJson());
Bson queryByOrderId = Filters.eq("order_id", orderId);
orders.updateOne(
queryByOrderId,
Updates.combine(
Updates.set("status", "PAID"),
Updates.set("paid_at", Instant.now())
)
);
Document paidOrder = orders.find(queryByOrderId).first();
System.out.println("paid order: " + paidOrder.toJson());
orders.deleteOne(queryByOrderId);
}
}
private static Properties loadProperties() throws IOException {
Properties properties = new Properties();
try (InputStream input = MongoHelloWorld.class
.getClassLoader()
.getResourceAsStream("application.properties")) {
if (input == null) {
throw new IllegalStateException("application.properties not found");
}
properties.load(input);
}
return properties;
}
}8. Run#
mvn -q compile exec:java -Dexec.mainClass=me.xiezhao.demo.MongoHelloWorldexpected:
found order: {"_id": ..., "order_id": "o-1001", ...}
paid order: {"_id": ..., "order_id": "o-1001", "status": "PAID", ...}9. How To Use In Real Project#
client lifecycle#
rule:
create MongoClient once when application starts
reuse it for all requests
close it when application stops
do not:
create MongoClient per requestpublic final class MongoProvider implements AutoCloseable {
private final MongoClient client;
private final MongoDatabase database;
public MongoProvider(String uri, String databaseName) {
this.client = MongoClients.create(uri);
this.database = client.getDatabase(databaseName);
}
public MongoCollection<Document> collection(String name) {
return database.getCollection(name);
}
@Override
public void close() {
client.close();
}
}repository pattern#
public final class OrderRepository {
private final MongoCollection<Document> orders;
public OrderRepository(MongoCollection<Document> orders) {
this.orders = orders;
}
public void createOrder(String orderId, String userId, BigDecimal amount) {
Document order = new Document("order_id", orderId)
.append("user_id", userId)
.append("status", "PENDING")
.append("amount", amount)
.append("created_at", Instant.now());
orders.insertOne(order);
}
public Document findByOrderId(String orderId) {
return orders.find(Filters.eq("order_id", orderId)).first();
}
public void markPaid(String orderId) {
orders.updateOne(
Filters.and(
Filters.eq("order_id", orderId),
Filters.eq("status", "PENDING")
),
Updates.combine(
Updates.set("status", "PAID"),
Updates.set("paid_at", Instant.now())
)
);
}
}repository should own:
collection name
query condition
update expression
index requirement
service should own:
business workflow
validation
transaction decision10. Production Checklist#
before coding:
write access patterns first
design document shape
design indexes
decide consistency requirement
application config:
URI comes from env / secret manager
appName is set
replicaSet is set for replica set
retryWrites is enabled when suitable
write concern is explicit for critical data
code:
reuse MongoClient
do not create client per request
set query limit
use projection for large documents
avoid skip for deep pagination
use update operators, not full document replacement by default
operation:
create index before production traffic
review explain for hot queries
monitor slow query
monitor connection pool
monitor replication lag11. Common Mistakes#
mistakes:
no index on hot query
full collection scan in API path
create MongoClient per request
large skip pagination
huge document / unbounded array
read from secondary without considering lag
use root user in application
expose MongoDB to public internet
no backup restore test