如何将数据从Cloud Firestore导入到本地模拟器?

时间:2019-09-08 02:28:04

标签: google-cloud-firestore google-cloud-functions firebase-tools

我希望能够在本地运行云功能并针对生产数据中的副本进行调试。 有没有办法将在线数据复制到本地Firestore模拟器?

7 个答案:

答案 0 :(得分:31)

这可以通过现有项目的终端中的一组命令来完成:

1。登录到Firebase和Gcloud:

firebase login
gcloud auth login

2。查看您的项目列表并连接到一个项目:

firebase projects:list
firebase use your-project-name

gcloud projects list
gcloud config set project your-project-name

3。使用所选名称将生产数据导出到gcloud存储桶:

gcloud firestore export gs://your-project-name.appspot.com/your-choosen-folder-name

4。现在,将此文件夹复制到您的本地计算机上,我直接在functions文件夹中执行此操作:

cd functions
gsutil -m cp -r gs://your-project-name.appspot.com/your-choosen-folder-name .

5。现在,我们只想导入此文件夹。感谢Firebase团队https://github.com/firebase/firebase-tools/pull/2519.

的最新更新,这应该可以与基本命令一起使用
firebase emulators:start --import ./your-choosen-folder-name

请查看我在Medium上的相关文章以及简化的脚本来https://medium.com/firebase-developers/how-to-import-production-data-from-cloud-firestore-to-the-local-emulator-e82ae1c6ed8

注意:最好使用其他存储桶,因为将其复制到项目存储桶中会导致在Firebase存储中创建文件夹。
如果您对-m之类的gsutil参数感兴趣,可以通过执行gsutil --help看到它们的描述。

答案 1 :(得分:11)

我的方法有些手动,但是可以解决问题。我已经在this useful Github thread中分享了它,但是如果您发现它们有用,我会在这里列出我执行的步骤:

  1. 转到我的本地Firebase项目路径。
  2. 使用以下命令启动仿真器:<template> <el-form :model="item" ref="item" label-width="120px"> <el-form-item label="Name" required> <el-input v-model="item.name" autocomplete="off"></el-input> </el-form-item> <el-form-item label="Description"> <el-input v-model="item.description"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click='submitForm'>Submit</el-button> <el-button @click='clearForm'>Clear</el-button> </el-form-item> </el-form> </template> <script> export default { name: 'itemForm', data () { return { item: { name: '', description:'' } } }, methods: { submitForm() { this.$store.dispatch('addItem', this.item) }, clearForm() { console.log("CLEAR") this.$refs['item'].resetFields() } }, watch: { item: function() { console.log(this.item) } } } </script>
  3. 使用提供的按钮,使用http://localhost:4000/firestore上的GUI,手动创建一些模型数据: +开始收集 +添加文档
  4. 使用firebase emulators:start
  5. 在本地导出此数据
  6. 关于位于 Firebase数据库/ Cloud Firestore 的项目数据,我导出了一个像这样的集合: emulators:export ./mydirectory现在,导出位于 Firebase Storage 下在一个带有时间戳的文件夹中(我没有在测试中使用前缀)
  7. 使用以下方式将此文件夹下载到本地驱动器:gcloud firestore export gs://my-project-bucket-id.appspot.com --collection-ids=myCollection注意:我是在Windows环境中执行的操作... gsutil 会引发此错误:“ OSError:filename,目录名称或卷标签语法不正确” ,如果该文件夹在Windows中具有无效的文件夹名称字符(例如冒号)或出现以下错误:“ OSError:Invalid arguments.9.0 B]” 如果文件夹中的内部文件也包含无效字符。为了能够在本地下载导出文件,请使用有效的Windows名称重命名这些文件(即删除冒号),例如:gsutil cp -r gs://my-project-bucket-id.appspot.com/myCollection ./production_data_export
  8. 下载后,模仿本地导出结构,将文件夹重命名为gsutil mv gs://my-project-bucket-id.appspot.com/2020-05-22T02:01:06_86152 gs://my-project-bucket-id.appspot.com/myCollection,然后从本地导出文件夹复制firestore_export文件。只是为了视觉,这是我得到的结构:
firebase-export-metadata.json
  1. 最后,启动指向要导入的生产数据的本地仿真器:$ tree . . ├── local_data_export │ ├── firebase-export-metadata.json │ └── firestore_export │ ├── all_namespaces │ │ └── all_kinds │ │ ├── all_namespaces_all_kinds.export_metadata │ │ └── output-0 │ └── firestore_export.overall_export_metadata └── production_data_export ├── firebase-export-metadata.json └── firestore_export ├── all_namespaces │ └── kind_myCollection │ ├── all_namespaces_kind_myCollection.export_metadata │ ├── output-0 │ └── output-1 └── firestore_export.overall_export_metadata 8 directories, 9 files
  2. 您应该在http://localhost:4000/firestore/
  3. 处看到导入的数据

当我们等待Firebase员工提供更强大的解决方案时,这应该现在对读者有帮助。

答案 2 :(得分:2)

没有内置的方法可以将数据从云项目复制到本地仿真器。由于仿真器不会保留任何数据,因此每次运行时都必须重新生成初始数据集。

答案 3 :(得分:2)

您可以使用firestore-backup-restore将生产数据导出和导入为JSON文件。

我写了一篇简短的文章,允许将这些JSON导入Firebase Simulator Firestore实例中。

我提出了拉取请求,与此同时提出了npm module

您可以通过以下方式使用它:

const firestoreService = require('@crapougnax/firestore-export-import')
const path = require('path')

// list of JSON files generated with the export service
// Must be in the same folder as this script
const collections = ['languages', 'roles']

// Start your firestore emulator for (at least) firestore
// firebase emulators:start --only firestore

// Initiate Firebase Test App
const db = firestoreService.initializeTestApp('test', {
   uid: 'john',
   email: 'john@doe.com',
})

// Start importing your data
let promises = []
try {
   collections.map(collection =>
      promises.push(
         firestoreService.fixtures(
            path.resolve(__dirname, `./${collection}.json`),
            [],
            [],
            db,
         ),
      ),
   )
   Promise.all(promises).then(process.exit)
} catch (err) {
   console.error(err)
}

显然,由于这些数据不会在模拟器中保留,因此通常将它们注入测试套件的before()函数中,甚至在每次测试之前。

希望这会有所帮助。

答案 4 :(得分:2)

我能够制作一些npm脚本,以便从远程导入到本地仿真器,反之亦然。

"serve": "yarn build && firebase emulators:start --only functions,firestore --import=./firestore_export",
"db:update-local-from-remote": "yarn db:backup-remote && gsutil -m cp -r gs://my-firebase-bucket.appspot.com/firestore_export .",
"db:update-remote-from-local": "yarn db:backup-local && yarn db:backup-remote && gsutil -m cp -r ./firestore_export gs://my-firebase-bucket.appspot.com && yarn run db:import-remote",
"db:import-remote": "gcloud firestore import gs://my-firebase-bucket.appspot.com/firestore_export",
"db:backup-local": "firebase emulators:export --force .",
"db:rename-remote-backup-folder": "gsutil mv gs://my-firebase-bucket.appspot.com/firestore_export gs://my-firebase-bucket.appspot.com/firestore_export_$(date +%d-%m-%Y-%H-%M)",
"db:backup-remote": "yarn db:rename-remote-backup-folder && gcloud firestore export gs://my-firebase-bucket.appspot.com/firestore_export"

因此您可以使用以下方法将本地Firestore数据导出到远程:

npm db:update-remote-from-local

或使用远程数据更新本地Firestore数据,请执行以下操作:

npm db:update-local-from-remote

这些操作将备份远程Firestore数据,将其复制并存储在Firebase Storage中。

答案 5 :(得分:0)

我本来打算向firebase-tools添加cli选项,但对node-firestore-import-export软件包非常满意。

yarn add -D node-firestore-import-export
  "scripts": {
    "db:export": "firestore-export -a ./serviceAccountKey.json -b ./data/firestore.json",
    "db:import": "firestore-import -a ./serviceAccountKey.json -b ./data/firestore.json",
    "db:emulator:export": "export FIRESTORE_EMULATOR_HOST=localhost:8080 && yarn db:export",
    "db:emulator:import": "export FIRESTORE_EMULATOR_HOST=localhost:8080 && yarn db:import",
    "db:backup": "cp ./data/firestore.json ./data/firestore-$(date +%d-%m-%Y-%H-%M).json",
    "dev": "firebase emulators:start --import=./data --export-on-exit=./data",
  },

您将需要在Firebase控制台中创建一个服务帐户。

您可以用硬编码值替换GCLOUD_PROJECT环境变量。

open https://console.firebase.google.com/project/$GCLOUD_PROJECT/settings/serviceaccounts/adminsdk
mv ~/Downloads/myProjectHecticKeyName.json ./serviceAccountKey.json

话虽这么说,gcloud工具绝对是进入生产环境的方式,因为无论如何您都需要s3备份。

答案 6 :(得分:0)

我写了一个小脚本来做到这一点:

const db = admin.firestore();
const collections = ['albums', 'artists'];
let rawData: any;
    
for (const i in collections) {
    rawData = fs.readFileSync(`./${collections[i]}.json`);
    const arr = JSON.parse(rawData);

    for (const j in arr) {
        db.collection(collections[i]).add(arr[j])
        .then(val => console.log(val))
        .catch(err => console.log('ERRO: ', err))
    }
        
}