一尘不染

使用查询的Cloud Firestore大小写不​​敏感排序

javascript

我尝试使用 OrderBy 从Cloud Firestore读取排序的数据。然后Firestore按照以下顺序返回数据:

AAA
BBB
aaa
bbb

现在,我想要的是以下内容:

AAA
AAA
BBB
BBB

我只希望使用 OrderBy 而不通过手动排序获得此结果。
在Firestore中,有什么方法可以排序?

请为此提供解决方案。

提前致谢。


阅读 359

收藏
2020-05-01

共1个答案

一尘不染

Cloud Firestore中的排序区分大小写。没有标志可以使排序忽略大小写。

实现用例的唯一方法是将字段存储两次。

假设您存储“ AAA”和“
aaa”的字段称为myData。在客户端代码中,您需要存储第二个字段,称为myData_insensitive存储不区分大小写的数据副本的位置。

DocA:
-> myData = 'AAA'
-> myData_insensitive = 'AAA'

DocB:
-> myData = 'aaa'
-> myData_insensitive = 'AAA'

DocC:
-> myData = 'BBB'
-> myData_insensitive = 'BBB'

DocD:
-> myData = 'bbb'
-> myData_insensitive = 'BBB'

现在,您可以通过查询和/或订购myData_insensitive,但显示myData

关于此区域的两个有趣的事情是:

  1. 使用Unicode,删除大小写不仅比’toLowerCase’更复杂
  2. 不同的人类语言会对相同的字符进行不同的排序

无需为每个排序规则创建单独的索引来解决(2),处理(1)的一种实现方法是通过大小写折叠。如果您只想支持现代浏览器版本,那么下面为您提供一个JavaScript示例:

caseFoldNormalize = function (s){
  return s.normalize('NFKC').toLowerCase().toUpperCase().toLowerCase()
};
caseFoldDoc = function(doc, field_options) {
  // Case fold desired document fields
  if (field_options != null) {
    for (var field in field_options) {
      if (field_options.hasOwnProperty(field)) {
        switch(field_options[field]) {
          case 'case_fold':
            if (doc.hasOwnProperty(field) && Object.prototype.toString.call(doc[field]) === "[object String]") {
              doc[field.concat("_insensitive")] = caseFoldNormalize(doc[field])
            }
            break;
        }
      }
    }
  }
  return doc;
}

var raw_document = {
  name: "Los Angeles",
  state: "CA",
  country: "USA",
  structure: 'Waſſerſchloß',
  message: 'quıt quit' // Notice the different i's
};

var field_options = {
  name: 'case_fold',
  country: 'case_fold',
  structure: 'case_fold',
  message: 'case_fold'
}

var firestore_document = caseFoldDoc(raw_document, field_options);

db.collection("cities").doc("LA").set(firestore_document).then(function() {
  console.log("Document successfully written!");
}).catch(function(error) {
  console.error("Error writing document: ", error);
});

这将为您提供Cloud Firestore中包含以下字段的文档:

{ 
 "name": "Los Angeles", 
 "state": "CA", 
 "country": "USA", 
 "structure": "Waſſerſchloß", 
 "message": "quıt quit", 
 "name_casefold": "los angeles", 
 "country_casefold": "usa", 
 "structure_casefold": "wasserschloss", 
 "message_casefold": "quit quit"
}
2020-05-01