面试题答案
一键面试查询条件构建策略
- 操作类型条件:直接在查询条件中指定
action
字段为login
,即{ action: 'login' }
。 - 时间范围条件:获取当前时间并减去一周时间,得到一周前的时间点。在JavaScript中示例代码如下:
const currentDate = new Date();
const oneWeekAgo = new Date(currentDate.getTime() - 7 * 24 * 60 * 60 * 1000);
const query = {
action: 'login',
timestamp: { $gte: oneWeekAgo }
};
在Python(使用 pymongo
库)中示例代码如下:
from datetime import datetime, timedelta
one_week_ago = datetime.now() - timedelta(days = 7)
query = {
"action": "login",
"timestamp": {
"$gte": one_week_ago
}
}
索引设计
- 复合索引:由于查询条件涉及
action
和timestamp
两个字段,创建复合索引可以显著提升查询性能。索引字段顺序应按照查询条件中过滤能力强的字段在前的原则。因为action
字段的离散度相对较小,timestamp
离散度较大且查询范围固定,所以复合索引顺序应为action
在前,timestamp
在后。 在MongoDB shell中创建复合索引命令如下:
db.your_collection_name.createIndex({ action: 1, timestamp: 1 });
在Python(pymongo
库)中创建复合索引代码如下:
from pymongo import MongoClient
client = MongoClient()
db = client.your_database_name
collection = db.your_collection_name
collection.create_index([("action", 1), ("timestamp", 1)])
性能优化措施
- 投影优化:如果不需要返回文档的所有字段,通过投影只返回需要的字段,可以减少数据传输量和查询响应时间。例如,若只需要
user_id
字段,在JavaScript中查询如下:
db.your_collection_name.find(query, { user_id: 1, _id: 0 });
在Python中:
result = collection.find(query, {"user_id": 1, "_id": 0})
-
定期清理过期数据:随着时间推移,集合中的文档会越来越多,查询性能会下降。定期删除
timestamp
不在关注范围内(比如超过一年的数据)的数据,可以减少集合的大小,从而提升查询性能。 -
分片:对于海量数据,考虑对集合进行分片。可以根据
user_id
等字段进行分片,这样可以将数据分布在多个分片服务器上,提高查询的并行处理能力。在MongoDB中设置分片集群需要一定的配置步骤,包括启动分片服务器、配置服务器,以及启用分片等操作。 -
使用合适的读偏好:如果读操作远多于写操作,并且部署了多个副本集成员,可以选择合适的读偏好(如
secondaryPreferred
),将读操作分发到副本集成员上,减轻主节点的负载。在JavaScript中可以如下设置:
const cursor = db.your_collection_name.find(query).readPref('secondaryPreferred');
在Python中:
result = collection.find(query, read_preference=ReadPreference.SECONDARY_PREFERRED)