一般排序是数据(doc/resultItem) 取出来之后,按某个某个字段的值排序。也就是必须拿到doc/resultItem之后才能排序。mds排序的特点是在取resultItem之前就排序,不是对resultItem排序,而是对docId/LabelIndex排序。
怎么实现的?只支持预先配置的排序,某种resultItem需要什么样的排序必须预先配置。比如配置了按name排序,那么会把所有的这种resultItem的 labelIndex按 name排序存一份。查询端根据这个全部labelIndex的排序建立每个lableIndex在这种排序下的顺序(rank),这就是为什么能对docId/lableIndex排序,因为有rank。这个问题通用的描述是,已知id全集的按某种顺序排好的集合,给你一个子集,让你对这个子集排序,使得这个子集里元素的相对循序和全集排好序的集合一致。
有两种思路,一种是对全集排序集合建立id的rank的hashmap, rank就是index。然后子集id的排序以它的rank作为key排序。
void sortB(int A[], int m, int B[], int n)
{
unordered_map<int,int> pos;
for(int i=0;i<m;i++)
pos[A[i]]==i;
sort(B,B+n, [&](int a, int b){return pos[a]<pos[b];});
}
第二种是对子集建立hashset, 遍历排好序的全集,如果遇到在子集hashset里的元素,输出,输出的顺序就是排好序的。
void sortB(int A[], int m, int B[],int n)
{
unordered_set<int> bSet;
for(int i=0;i<n;i++)
bSet.insert(B[i]);
for(int i=0,j=0;i<m;i++)
if(bSet.find(A[i])!=bSet.end())
B[j++]=A[i];
}
现实情况下,全集很大不宜每个查询都遍历一遍,而且对子集(每一具体查询结果集)的排序是经常做的,所以采用的是第一种方法。
MDS的这种静态排序跟一般数据库的排序比较:
1)只支持预先配置的排序
2)实时的排序过程是根据id的rank对id排序,排序过程中的比较,交换元素都是int,跟排序字段类型无关,也就是不需要处理字符串等的比较。
3)需要额外的空间,针对每种排序,都需要维护所有id在这种排序下的rank
4) 总的来说,在建立数据的时候预先排序,在查询期间只需要进行简单的对int的排序。空间换时间,还是不错的方案。