关于javascript:使用查询的Cloud Firestore案例不敏感排序

Cloud Firestore Case Insensitive Sorting Using Query

我尝试使用orderby从云FireStore读取排序数据。FireStore返回数据的顺序如下:

AAA<BR/>BBB
AAA<BR/>血脑屏障

现在,我想要的是如下:

AAA<BR/>AAA<BR/>BBB
血脑屏障

我只希望使用orderby而不是手动排序的结果。
在消防商店有没有办法这样分类?请给我一个解决办法。

事先谢谢。


云FireStore中的排序区分大小写。没有使排序忽略案例的标志。

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

假设您存储"aaa"的字段称为myData。在您的客户机代码中,您需要存储第二个名为myData_insensitive的字段,在该字段中存储数据的不区分大小写的副本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

这个地区有两个有趣的地方:

  • 使用Unicode时,移除大小写比"ToLowercase"更复杂。
  • 不同的人类语言会对相同的字符进行不同的排序
  • 不为每个排序规则创建单独的索引来解决(2),处理(1)的一种实现方法是通过案例折叠。如果您只想支持现代浏览器版本,那么下面给出一个javascript示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    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);
    });

    这将在CloudFireStore中为您提供一个包含以下字段的文档:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    {
    "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"
    }

    要处理较旧的浏览器,您可以看到一个解决方案,即如何使tolowercase()和touppercase()在浏览器之间保持一致


    您也可以在获得结果后手动执行此操作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    docArray.sort((a, b) => {
      if (a.myData.toLowerCase() < b.myData.toLowerCase()) {
        return -1;
      }
      if (a.myData.toLowerCase() > b.myData.toLowerCase()) {
        return 1;
      }
      return 0;
    });