【问题标题】:How to delete all documents from Gcloud beta emulators firestore?如何从 Gcloud beta 模拟器 Firestore 中删除所有文档?
【发布时间】:2019-11-13 21:47:10
【问题描述】:

我正在创建一些简单的应用程序来学习 Firestore。

我启动了本地 Firestore 模拟器:

$ gcloud beta 模拟器 firestore start

启动模拟器后,我用“go test”运行测试

我用数据填充了 Firestore,并创建了一个函数来查询添加的一些记录/文档。

我从我的应用程序中删除了一些文档,但它们继续显示在查询中。

我试过了:

  • 用 ctrl-c 和 ctrl d 停止

  • $ gcloud beta 模拟器 firestore stop

  • 重新启动我的 Macbook,但文档仍然存在。

我不明白重新启动计算机后数据存储是如何持续存在的,我猜数据存储在 JSON 文件或类似文件中。

我搜索了但无法在模拟器上找到任何文档。

我是否应该启动模拟器,然后针对模拟的 Firestore 运行测试?

如何刷新 Firestore?

【问题讨论】:

  • 只是为了确定一下,您是否设置了 FIRESTORE_EMULATOR_HOST=::1:PORT 环境变量以将您的应用程序连接到模拟器?
  • 不,我没有那样做。我只是用“go test”运行一些测试
  • 如果您没有设置FIRESTORE_EMULATOR_HOST,那么您可能连接到项目的 Cloud Firestore 数据库而不是本地模拟器。您的目标是使用模拟器进行本地测试吗?请注意,模拟器是可选的。如果您正在创建简单的应用程序来学习,您应该可以连接到您的真实数据库并使用free quota

标签: go google-cloud-firestore gcloud


【解决方案1】:

模拟器支持端点清库(docs):

curl -v -X DELETE "http://localhost:PORT/emulator/v1/projects/PROJECT_NAME/databases/(default)/documents"

填写PORTPROJECT_NAME

【讨论】:

    【解决方案2】:

    由于您使用的是 Go,这里有一个我实现的小测试助手,它可以帮助启动模拟器、等待它启动、清除现有数据、初始化客户端以及在完成后关闭操作员。

    它使用了 Juan 的答案中的技术(你应该将其标记为答案)。

    要使用此实用程序,您只需说:

    client := startFirestoreEmulator(t)
    

    源代码:

    // Copyright 2021 Ahmet Alp Balkan
    //
    // Licensed under the Apache License, Version 2.0 (the "License");
    // you may not use this file except in compliance with the License.
    // You may obtain a copy of the License at
    //
    //      http://www.apache.org/licenses/LICENSE-2.0
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.
    
    // Package firestoretestutil contains test utilities for starting a firestore
    // emulator locally for unit tests.
    package firestoretestutil
    
    import (
        "bytes"
        "context"
        "fmt"
        "net"
        "net/http"
        "os"
        "os/exec"
        "sync"
        "testing"
        "time"
    
        firestore "cloud.google.com/go/firestore"
    )
    
    const firestoreEmulatorProj = "dummy-emulator-firestore-project"
    
    // cBuffer is a buffer safe for concurrent use.
    type cBuffer struct {
        b bytes.Buffer
        sync.Mutex
    }
    
    func (c *cBuffer) Write(p []byte) (n int, err error) {
        c.Lock()
        defer c.Unlock()
        return c.b.Write(p)
    }
    
    func StartEmulator(t *testing.T, ctx context.Context) *firestore.Client {
        t.Helper()
        port := "8010"
        addr := "localhost:" + port
        ctx, cancel := context.WithCancel(ctx)
        t.Cleanup(func() {
            t.Log("shutting down firestore operator")
            cancel()
        })
    
        // TODO investigate why there are still java processes hanging around
        // despite we kill the exec'd command, suspecting /bin/bash wrapper that gcloud
        // applies around the java process.
        cmd := exec.CommandContext(ctx, "gcloud", "beta", "emulators", "firestore", "start", "--host-port="+addr)
        out := &cBuffer{b: bytes.Buffer{}}
        cmd.Stderr, cmd.Stdout = out, out
        if err := cmd.Start(); err != nil {
            t.Fatalf("failed to start firestore emulator: %v -- out:%s", err, out.b.String())
        }
        dialCtx, clean := context.WithTimeout(ctx, time.Second*10)
        defer clean()
        var connected bool
        for !connected {
            select {
            case <-dialCtx.Done():
                t.Fatalf("emulator did not come up timely: %v -- output: %s", dialCtx.Err(), out.b.String())
            default:
                c, err := (&net.Dialer{Timeout: time.Millisecond * 200}).DialContext(ctx, "tcp", addr)
                if err == nil {
                    c.Close()
                    t.Log("firestore emulator started")
                    connected = true
                    break
                }
                time.Sleep(time.Millisecond * 200) //before retrying
            }
        }
        os.Setenv("FIRESTORE_EMULATOR_HOST", addr)
        cl, err := firestore.NewClient(ctx, firestoreEmulatorProj)
        if err != nil {
            t.Fatal(err)
        }
        os.Unsetenv("FIRESTORE_EMULATOR_HOST")
        truncateDB(t, addr)
        return cl
    }
    
    func truncateDB(t *testing.T, addr string) {
        t.Helper()
        // technique adopted from https://stackoverflow.com/a/58866194/54929
        req, _ := http.NewRequest(http.MethodDelete, fmt.Sprintf("http://%s/emulator/v1/projects/%s/databases/(default)/documents",
            addr, firestoreEmulatorProj), nil)
        resp, err := http.DefaultClient.Do(req)
        if err != nil {
            t.Fatal(err)
        }
        if resp.StatusCode != http.StatusOK {
            t.Fatalf("failed to clear db: %v", resp.Status)
        }
    }
    

    【讨论】:

      【解决方案3】:

      你可以用这个:

      module.exports.teardown = async () => {
        Promise.all(firebase.apps().map(app => app.delete()));
      };
      

      现在,每次调用 teardown,您都会从 Firestore 模拟器中删除所有数据。

      【讨论】:

      • 开发计算机重启后数据如何保留?这看起来像一个 Node.js sn-p。我正在用 Golang 编码。
      猜你喜欢
      • 2018-10-19
      • 1970-01-01
      • 2021-09-29
      • 2020-09-01
      • 2020-09-08
      • 2020-12-11
      • 2019-03-20
      相关资源
      最近更新 更多