【问题标题】:Access Firestore ID generator on the front end在前端访问 Firestore ID 生成器
【发布时间】:2019-10-27 16:47:12
【问题描述】:

我想在前端设置我的文档ID,同时我set文档,所以我想知道是否有一种方法可以生成Firestore ID,它可能看起来像这样:

const theID = firebase.firestore().generateID() // something like this

firebase.firestore().collection('posts').doc(theID).set({
    id: theID,
    ...otherData
})

我可以使用 uuid 或其他一些 id 生成器包,但我正在寻找 Firestore id 生成器。 This SO answer 指向一些newId method,但是我在JS SDK 中找不到... (https://www.npmjs.com/package/firebase)

【问题讨论】:

    标签: javascript firebase google-cloud-firestore


    【解决方案1】:

    是否要添加具有唯一 ID 的新文档?

    https://firebase.google.com/docs/firestore/manage-data/add-data#add_a_document

    有时文档没有有意义的 ID,让 Cloud Firestore 为您自动生成 ID 会更方便。你可以通过调用 add() 来做到这一点

    在某些情况下,使用自动生成的 ID 创建文档引用会很有用,然后再使用该引用。对于这个用例,你可以调用 doc()

    在幕后,.add(...) 和 .doc().set(...) 是完全等价的,所以你可以使用哪个更方便。

    添加()

        // Add a new document with a generated id.
        db.collection("cities").add({
            name: "Tokyo",
            country: "Japan"
        })
        .then(function(docRef) {
            console.log("Document written with ID: ", docRef.id);
        })
        .catch(function(error) {
            console.error("Error adding document: ", error);
        });test.firestore.js
    

    doc()

        // Add a new document with a generated id.
        var newCityRef = db.collection("cities").doc();
        // later...
        newCityRef.set(data);
    

    【讨论】:

    • 我知道我可以使用 add() 让 Firestore 为我自动生成 ID。我想知道的是我是否可以通过前端的某种方法调用在创建文档之前生成 id。像这样,如果我想将 id 存储在文档数据中,我不需要进行额外的查询。
    • 为什么要将id存储在文档数据中?为什么不使用 DocumentReference.id?见firebase.google.com/docs/reference/js/…
    【解决方案2】:

    编辑:Chris Fischer 的回答更加最新,使用crypto 生成随机字节可能更安全(尽管在非节点环境中尝试使用crypto 可能会遇到问题,例如 React Native)。

    原答案:

    在 RN Firebase 不和谐聊天中询问后,我被指向 react-native-firebase 库深处的this util function。它本质上与我在问题中提到的 SO 答案所指的功能相同(参见 firebase-js-sdk here 中的代码)。

    根据您在 Firebase 周围使用的包装器,ID 生成工具不一定是导出/可访问的。所以我只是将它作为一个util函数复制到我的项目中:

    export const firestoreAutoId = (): string => {
      const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
    
      let autoId = ''
    
      for (let i = 0; i < 20; i++) {
        autoId += CHARS.charAt(
          Math.floor(Math.random() * CHARS.length)
        )
      }
      return autoId
    }
    

    抱歉,回复晚了:/希望这会有所帮助!

    【讨论】:

      【解决方案3】:
      import {randomBytes} from 'crypto';
      
      export function autoId(): string {
        const chars =
          'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        let autoId = '';
        while (autoId.length < 20) {
          const bytes = randomBytes(40);
          bytes.forEach(b => {
            // Length of `chars` is 62. We only take bytes between 0 and 62*4-1
            // (both inclusive). The value is then evenly mapped to indices of `char`
            // via a modulo operation.
            const maxValue = 62 * 4 - 1;
            if (autoId.length < 20 && b <= maxValue) {
              autoId += chars.charAt(b % 62);
            }
          });
        }
        return autoId;
      }
      

      取自 Firestore Node.js SDK: https://github.com/googleapis/nodejs-firestore/blob/4f4574afaa8cf817d06b5965492791c2eff01ed5/dev/src/util.ts#L52

      【讨论】:

      • 由于加密库不可用,我无法使用 typescript 进行此操作。我试图让它与crypto-js一起工作,但放弃了。如果有人找到解决方案会很感兴趣
      • 查看我刚刚发布的解决方案@jcroll
      【解决方案4】:

      另一种选择是:

      1. 安装@google-cloud/firestore npm install @google-cloud/firestore

      2. 然后在需要的时候导入并使用autoId

      import {autoId} from "@google-cloud/firestore/build/src/util";
      

      【讨论】:

        【解决方案5】:

        我找不到如何从 firestore 库访问 AutoId.newId()。但是,实际上有一种更安全的方法可以从浏览器的 window.crypto 库中获取 ID(TypeScript 中的代码示例 - 只需删除 JS 的类型)。

        // Use crypto api to generate random string of given length (in bytes)
        // Note that characters are hex bytes - so string is twice as long as
        // requested length - but has 8 * bytes bits of entropy.
        function generateId(bytes: number): string {
            let result = "";
            // Can't use map as it returns another Uint8Array instead of array
            // of strings.
            for (let byte of crypto.getRandomValues(new Uint8Array(bytes))) {
                result += byte.toString(16);
            }
            return result;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-09-15
          • 2018-09-10
          • 2018-06-29
          • 1970-01-01
          • 1970-01-01
          • 2021-03-29
          相关资源
          最近更新 更多