我希望能够在本地运行云功能并针对生产数据中的副本进行调试。 有没有办法将在线数据复制到本地Firestore模拟器?
答案 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中分享了它,但是如果您发现它们有用,我会在这里列出我执行的步骤:
<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>
firebase emulators:start
emulators:export ./mydirectory
现在,导出位于 Firebase Storage 下在一个带有时间戳的文件夹中(我没有在测试中使用前缀)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
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
$ 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
当我们等待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))
}
}