Để tạo index cho trường lồng nhau (nested field) trong MongoDB, bạn sử dụng createIndex() (hoặc ensureIndex() deprecated) với dot notation.
Cú pháp
db.yourCollectionName.createIndex({"outerField.innerField.secondInnerField": 1});
Ví dụ minh họa
Tạo collection với document lồng nhau sâu
> db.nestedIndexDemo.insertOne({
"CustomerId": 101,
"CustomerDetails": {
"CustomerListDetails": {
"CustomerName": "Larry",
"CustomerProjectName": "Project-1",
"CustomerCountryName": "US"
}
}
});
{ "acknowledged" : true, "insertedId" : ObjectId("5c8fc565d3c9d04998abf010") }
Xem dữ liệu
> db.nestedIndexDemo.find().pretty();
{
"_id" : ObjectId("5c8fc565d3c9d04998abf010"),
"CustomerId" : 101,
"CustomerDetails" : {
"CustomerListDetails" : {
"CustomerName" : "Larry",
"CustomerProjectName" : "Project-1",
"CustomerCountryName" : "US"
}
}
}
Tạo nested index trên CustomerCountryName (3 cấp lồng)
> db.nestedIndexDemo.createIndex({"CustomerDetails.CustomerListDetails.CustomerCountryName": 1});
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
Kiểm tra indexes
> db.nestedIndexDemo.getIndexes();
[
{
"v" : 2,
"key" : { "_id" : 1 },
"name" : "_id_",
"ns" : "test.nestedIndexDemo"
},
{
"v" : 2,
"key" : { "CustomerDetails.CustomerListDetails.CustomerCountryName" : 1 },
"name" : "CustomerDetails.CustomerListDetails.CustomerCountryName_1",
"ns" : "test.nestedIndexDemo"
}
]
Đặc điểm Nested Index
- Hỗ trợ truy vấn nhanh trên trường sâu:
db.coll.find({"CustomerDetails.CustomerListDetails.CustomerCountryName": "US"}) - Tên index tự động sinh từ đường dẫn trường
- Có thể tạo compound index mix trường root và nested
Compound Index với trường nested
// Index trên CustomerId (root) + CustomerCountryName (nested)
db.nestedIndexDemo.createIndex({
"CustomerId": 1,
"CustomerDetails.CustomerListDetails.CustomerCountryName": 1
});
Truy vấn tận dụng nested index
// Equality match
db.nestedIndexDemo.find({"CustomerDetails.CustomerListDetails.CustomerCountryName": "US"});
// Range query
db.nestedIndexDemo.find({"CustomerDetails.CustomerListDetails.CustomerCountryName": {$gte: "U"}});
// Compound query
db.nestedIndexDemo.find({
"CustomerId": 101,
"CustomerDetails.CustomerListDetails.CustomerCountryName": "US"
});
Lưu ý
- Index nested hoạt động như index thông thường
- Không thể tạo index trên trường mảng lồng nhau nếu đã có multikey index khác (compound multikey limit)
- Index size tăng theo độ sâu và cardinality
- Dùng
explain()để verify index được sử dụng