面试题答案
一键面试视图设计
- 映射函数:
- 在CouchDB中,视图是通过映射函数和可选的化简函数来定义的。对于嵌套数据的排序查询,映射函数需要提取出用于排序的嵌套字段。
- 例如,如果文档结构为
{ "person": { "name": "John", "age": 30, "address": { "city": "New York" } } }
,且需要根据age
和city
排序。映射函数如下:
function(doc) { if (doc.person && doc.person.age && doc.person.address && doc.person.address.city) { emit([doc.person.age, doc.person.address.city], null); } }
- 这里使用数组
[doc.person.age, doc.person.address.city]
作为emit
的第一个参数,以便按age
和city
的顺序进行排序。如果有更多嵌套字段用于排序,依次添加到数组中。
- 化简函数(可选):
- 化简函数通常用于聚合数据。但在排序查询场景下,如果只需要按多个字段排序获取文档列表,可不使用化简函数。若有聚合需求,例如求每个城市不同年龄段的人数,可以使用化简函数。
- 例如:
function(keys, values, rereduce) { return values.length; }
索引创建与性能优化
- 索引创建:
- CouchDB会根据视图的映射函数自动创建索引。为了确保查询性能,要保证视图的映射函数定义准确,包含所有用于排序的关键嵌套字段。
- 可以通过
_view_cleanup
端点定期清理未使用的视图,以优化磁盘空间和索引管理。
- 处理嵌套数据:
- 在映射函数中,要仔细检查嵌套字段是否存在,避免因缺失字段导致文档在视图中不被正确处理。
- 对于复杂的嵌套结构,可以使用辅助函数来简化映射函数的逻辑,提高可读性和维护性。例如:
function getNestedValue(obj, path) { return path.split('.').reduce((acc, part) => acc && acc[part], obj); } function(doc) { const age = getNestedValue(doc, 'person.age'); const city = getNestedValue(doc, 'person.address.city'); if (age && city) { emit([age, city], null); } }
- 避免性能瓶颈:
- 批量查询:尽量使用批量查询,减少单次查询的数据量。可以通过
limit
参数限制返回的文档数量,通过skip
参数分页获取数据。 - 缓存:利用应用层的缓存机制,缓存经常查询的视图结果,减少对CouchDB的直接查询次数。
- 索引维护:定期分析和优化视图索引。如果数据量有大幅增长或结构发生变化,可能需要重新评估视图设计和索引策略。
- 减少不必要的字段返回:在查询时,只请求需要的字段,避免返回整个文档,减少网络传输和处理开销。例如使用
?include_docs=true&fields=person.name
只返回person.name
字段。
- 批量查询:尽量使用批量查询,减少单次查询的数据量。可以通过