簡體   English   中英

Cloud Firestore 使用查詢進行不區分大小寫的排序

[英]Cloud Firestore Case Insensitive Sorting Using Query

我嘗試使用OrderBy從 Cloud Firestore 讀取排序數據。 Firestore 按以下順序返回數據:

AAA級
BBB
啊啊
bbb

現在,我想要的是如下內容:

AAA級
啊啊
BBB
bbb

我希望這個結果只使用OrderBy而不是手動排序。
在 Firestore 中有沒有辦法像這樣排序?


請為此提供解決方案。

提前致謝。

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"
}

要處理舊瀏覽器,您可以在如何使瀏覽器中的toLowerCase()和toUpperCase()之間找到一個解決方案

現在是 2022 年。Firebase太棒了。 Firestore很棒 您無需因為此限制而停止使用 Firestore。 noSQL 世界上的一些東西是故意制造的,只是為了加快速度。

在這種情況下,您可以做的只是在文檔上創建另一個屬性,您可以在其中解析源值並將其小寫。 然后您可以使用解析的屬性對事物進行排序/排序。

例子:

interface ICompany {
  dateAdded: Date
  dateEdited: Date
  description: string
  id?: string
  logo?: string
  managers?: ICompanyManager
  name: string
  nameLowercase: string
  website?: string
}

如果您想按name對公司進行排序,請在此處。 你可以做什么:

query(
  companiesCollection,
  orderBy('nameLowercase', 'asc'),
)

添加/編輯時:

const company = await addDoc(companiesCollection, {
  name: data.name,
  nameLowercase: data.name.toLowerCase(),
  description: data.description,
  website: data.website,
  dateAdded: new Date(),
  dateEdited: new Date(),
} as ICompany)

瞧。

您可以在獲得結果后手動執行此操作:

docArray.sort((a, b) => {
  if (a.myData.toLowerCase() < b.myData.toLowerCase()) {
    return -1;
  }
  if (a.myData.toLowerCase() > b.myData.toLowerCase()) {
    return 1;
  }
  return 0;
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM