使用查询的Cloud Firestore案例不敏感排序

Mit*_*eya 15 javascript firebase google-cloud-firestore

我尝试使用OrderBy从Cloud Firestore读取已排序的数据.Firestore按以下顺序返回数据:

AAA
BBB
aaa
bbb

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

AAA
aaa
BBB
bbb

我希望这个结果只使用OrderBy而不是手工排序.
有没有办法在Firestore中这样排序?


请为我提供一个解决方案.

提前致谢.

Dan*_*ath 18

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'
Run Code Online (Sandbox Code Playgroud)

现在您可以查询和/或排序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);
});
Run Code Online (Sandbox Code Playgroud)

这将在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"
}
Run Code Online (Sandbox Code Playgroud)

要处理旧浏览器,您可以在如何使浏览器中的toLowerCase()和toUpperCase()之间找到一个解决方案

  • 如果我们想添加对具有大量文档的现有集合中的字段进行查询或排序的支持怎么样?所以我们需要扫描所有文档并为每个文档添加小写或大写的额外字段? (3认同)
  • 我使用Firebase的次数越多,我想使用的次数越少,这种简单的事情又怎么会变得如此不必要的复杂 (2认同)
  • 简直难以置信! (2认同)