Firestore安全规则:如何禁止languages集合中code字段重复?
Fixing Duplicate Code Validation in Firestore Security Rules
Let's break down why your current rule isn't working and fix it step by step:
What's Wrong with Your Existing Rule
- Incorrect Match Path: Your rule targets individual documents in the
/languages/{language}collection, but your data structure shows you're storing multiple language entries inside a single document'slanguagesfield (a map of{code, name}objects). The rule isn't checking the right data structure at all. - Misused
hasAny: ThehasAnycheck you wrote referencesrequest.resource.code, which doesn't exist—request.resourcerefers to the entire document being written, and your structure nestscodeinside thelanguagesmap. Even if that reference was correct, the rule wouldn't scan all existingcodevalues in the map.
The Correct Approach
To validate that all code values in the languages map are unique, you need to:
- Extract all
codevalues from the incominglanguagesmap. - Check for duplicates by comparing the length of the
codearray to the size of a set created from that array (sets automatically remove duplicates, so matching lengths mean no repeats).
Updated Security Rule
Adjust the document path to match where your languages map is stored (e.g., /appSettings/{settings} in the example below):
service cloud.firestore { match /databases/{database}/documents { match /appSettings/{settings} { allow write: if // Skip validation if `languages` isn't being updated !request.resource.data.keys().has('languages') || ( // Convert the `languages` map into an array of its values let languageEntries = request.resource.data.languages.values(), // Extract all `code` values into a single array let codes = languageEntries.map(entry => entry.code), // Ensure no duplicates exist (set size equals array length) codes.size() == codes.toSet().size() ); } } }
Key Explanations:
request.resource.data.languages.values()turns yourlanguagesmap into an array of the nested{code, name}objects.map(entry => entry.code)creates a flat array containing only thecodevalues for easy comparison.codes.toSet().size()gives the count of unique codes—if this matches the original array's length, there are no duplicates.
If You Intended Individual Language Documents
If you actually want to store each language as a separate document in the /languages collection:
- The simplest fix is to use the
codevalue as the document ID (e.g.,/languages/Fr,/languages/En). Firestore automatically prevents duplicate document IDs in a collection, so this enforces uniqueness by design. - If you can't use
codeas the ID, you'd need a separate collection to track existing codes (e.g.,/usedLanguageCodes/{code}) and validate against it in rules, but this requires transactional writes to keep the tracking collection in sync.
内容的提问来源于stack exchange,提问作者Taha Azzabi
相关产品推荐
相关产品推荐

