面试题答案
一键面试索引优化
- 创建文本索引:使用
createIndex
方法为需要搜索的字段创建文本索引。例如:
db.collection('yourCollection').createIndex({ field1: "text", field2: "text" });
多个字段的文本索引可以提高复杂文本搜索的效率。
2. 复合索引:对于涉及多个条件的查询,包括文本搜索与其他条件(如地理位置),创建复合索引。例如,若要结合地理位置与文本搜索,假设地理位置字段为location
(需是GeoJSON
格式),可以创建如下复合索引:
db.collection('yourCollection').createIndex({ location: "2dsphere", field1: "text" });
复合索引的顺序很重要,应将选择性高(区分度大)的字段放在前面。
查询语句优化
- 限制返回字段:只返回需要的字段,减少数据传输量。例如:
db.collection('yourCollection').find({ $text: { $search: "yourSearchText" } }, { field1: 1, _id: 0 });
这里只返回field1
字段,并且不返回_id
字段(默认会返回_id
)。
2. 合理使用操作符:对于文本搜索,$text
操作符是MongoDB专门用于文本搜索的,它比正则表达式搜索效率高很多。避免使用正则表达式进行全文搜索,除非有特殊需求。例如,使用$text
进行搜索:
db.collection('yourCollection').find({ $text: { $search: "yourSearchText" } });
- 批量查询:如果需要获取大量数据,使用批量查询方式,每次返回一定数量的数据,减少单次查询的负载。在Node.js中可以使用
cursor
进行批量操作,例如:
const cursor = db.collection('yourCollection').find({ $text: { $search: "yourSearchText" } });
cursor.each((err, doc) => {
if (doc) {
// 处理文档
} else {
// 处理完所有文档
}
});
服务器配置优化
- 内存配置:确保服务器有足够的内存,MongoDB会将经常访问的数据和索引缓存到内存中,以提高读取性能。合理设置
wiredTigerCacheSizeGB
参数,一般建议设置为服务器物理内存的50% - 75%,但不要超过可用内存。例如,在mongod.conf
文件中设置:
storage:
wiredTiger:
engineConfig:
cacheSizeGB: 8
- CPU资源:选择高性能的CPU,以应对大量的计算任务,尤其是在进行复杂查询和索引构建时。多核心CPU可以提高并行处理能力。
- 存储优化:使用高速存储设备,如SSD,相比传统的HDD,SSD可以显著提高I/O性能,减少数据读写的延迟。
结合地理位置与文本搜索、排序和分页的实现
- 数据准备:确保地理位置字段采用
GeoJSON
格式存储,例如:
{
"name": "Some Place",
"location": {
"type": "Point",
"coordinates": [longitude, latitude]
},
"description": "A description of the place"
}
- 索引创建:如前面提到,创建复合索引:
db.collection('yourCollection').createIndex({ location: "2dsphere", description: "text" });
- 查询实现:假设要搜索距离某个点一定范围内且包含特定文本的文档,并按某个字段排序和分页。例如,在Node.js中:
const { MongoClient } = require('mongodb');
const uri = "mongodb://localhost:27017";
const client = new MongoClient(uri);
async function searchAndSort() {
try {
await client.connect();
const db = client.db('yourDatabase');
const collection = db.collection('yourCollection');
const searchText = "yourSearchText";
const center = { type: "Point", coordinates: [longitude, latitude] };
const maxDistance = 10000; // 10公里
const page = 1;
const limit = 10;
const result = await collection.find({
location: {
$near: {
$geometry: center,
$maxDistance: maxDistance
}
},
$text: { $search: searchText }
})
.sort({ someField: 1 })
.skip((page - 1) * limit)
.limit(limit)
.toArray();
console.log(result);
} finally {
await client.close();
}
}
searchAndSort();
这里通过$near
操作符来实现地理位置的范围查询,结合$text
进行文本搜索,然后使用sort
进行排序,skip
和limit
实现分页。