CouchDB复合键排序疑问:整数为何按数值而非字符串排序?
解答:CouchDB复合键排序的类型差异问题
嘿,这个困惑其实是因为你误解了博客里的场景前提和CouchDB复合键的真实排序逻辑,咱们一步步拆解清楚:
1. 博客里的场景是「字符串类型的数字元素」,而非数值类型
你看到的博客案例中,数组里的数字之所以按字符串排序,是因为这些数字本身是字符串类型(比如Map函数里写的是emit(["2012", "Deer", "1"], ...))。当元素是字符串时,CouchDB会按Unicode码点逐个字符比较:"10"的第一个字符是'1',而"2"的第一个字符是'2','1'的码点比'2'小,所以"10"会排在"2"前面。
2. CouchDB复合键的真实排序逻辑:逐个元素+类型优先
CouchDB对复合键(数组)的排序绝对不是把整个数组转成字符串比较,而是遵循一套明确的规则:
- 按数组的元素顺序依次比较:先比第一个元素,第一个相等再比第二个,以此类推;
- 元素比较先看类型,类型优先级为:
null < 布尔值 < 数字 < 字符串 < 对象 < 数组; - 同类型元素的比较:数字按数值大小排序,字符串按Unicode码点逐个字符排序,数组则递归应用上述规则。
3. 你的测试结果为什么符合预期?
你的Map函数里emit([doc.changeDate,doc.terminalUser.userName], doc._id),这里的doc.changeDate是数值类型(比如时间戳本身就是数字)。所以第一个元素的比较是数值比较:2 < 1524823966903,因此[2, "test"]自然排在[1524823966903, "test"]前面。
如果想复现博客里的字符串排序场景,你可以把doc.changeDate转成字符串试试:
function (doc) { emit([String(doc.changeDate),doc.terminalUser.userName], doc._id); }
这时候"2"和"1524823966903"会按字符串规则比较,"15..."的第一个字符'1'比'2'小,就会排在"2"前面了。
内容的提问来源于stack exchange,提问作者rematnarab
相关产品推荐
相关产品推荐

