最近在实现一个需求的时候,需求要求查询的数据需要根据播放量倒叙、创建时间倒叙来排序,考虑到播放量、创建时间都有可能是相同的,就会出现排序不稳定的情况,于是就加入了"_id"作为第三个排序字段,在我进行DEBUG的时候,发现Query对象生成的查询语句居然把"_id"作为了第一个排序字段:
- Query query = new Query();
- List
orders = new ArrayList<>(); - orders.add(Sort.Order.desc("aa"));
- orders.add(Sort.Order.desc("bb"));
- orders.add(Sort.Order.asc("_id"));
- query.with(Sort.by(orders));
- System.out.println(SerializationUtils.serializeToJsonSafely(query.getSortObject()));
{ "_id" : 1, "aa" : -1, "bb" : -1 }
从代码的逻辑上来说,正确的查询语句应该是:
Sort: { "aa" : -1, "bb" : -1,"_id" : 1, }
而我们看到的却是"_id"被提前了:
Sort: { "_id" : 1, "aa" : -1, "bb" : -1 }
1、跟踪代码,看看为什么会生成这样的内容:
1)、在DocumentCodec.beforeFields方法中,如果发现排序的字段中有"_id",则优先写入
2)、在DocumentCodec.skipField方法中,如果发现排序的字段中有"_id",则跳过写入
经过这样一波神操作,我们在使用SerializationUtils.serializeToJsonSafely(query.getSortObject())输出排序字段的JSON格式内容的时候,"_id"字段被调到第一位了。
当我们看到这个Query被生成成这样的时候,心头一紧,咋回事?难度spring-data-mongodb不能实现我的诉求吗?我们来看看最终发送到MongoDB集群里面的语句是什么样子的:
从上图的DEBUG来看,发送到MongoDB里面的数据是正确的,并没有把“_id”排到第一,后面针对集合里面的数据进行验证,也发现没问题。
1、“_id”排序在执行的时候没有问题
2、“_id”排序在Query对象生成toString方法中写的有问题,应该是刻意为之,不知道是为什么