使用此命令,我能够轻松地将实体导出到存储桶中:
gcloud datastore export --kinds="KIND1,KIND2" --namespaces="NAMESPACE1,NAMESPACE2" gs://${BUCKET}
根据文档的导入,可以这样完成:
gcloud datastore import gs://${BUCKET}/[PATH]/[FILE].overall_export_metadata
或类似这样:
curl \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
https://datastore.googleapis.com/v1/projects/${PROJECT_ID}:import \
-d '{
"inputUrl": "gs://'${BUCKET}'/[PATH]/[FILE].overall_export_metadata",
}'
我的数据存储模拟器运行在localhost:8081
上,是否可以使用curl命令将数据导入模拟器?文档中没有关于它的任何内容,我已经尝试猜测许多URL,但是没有任何作用。
如果这不可能,那么还有其他方法可以填充本地仿真器,或者更好地将本地应用程序引擎连接到生产数据存储区吗?
显然以前曾经有一种使用csv文件导出和导入的方法:
Google cloud datastore emulator init data
但此后已弃用。
答案 0 :(得分:1)
由于Datastore模拟器似乎没有导入功能,因此您可以构建自己的
。这就像在脚本中创建两个客户端一样简单,一个用于远程(云)数据存储,一个用于本地数据存储模拟器。由于Cloud Client Libraries支持仿真器,因此您可以深入研究代码以了解如何正确建立连接。
我对go Cloud Client Libraries确实做到了,并提出了以下脚本:
package main
import (
"context"
"fmt"
"os"
"time"
"cloud.google.com/go/datastore"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
"google.golang.org/grpc"
)
const (
projectId = "<PROJECT_ID>"
namespace = "<NAMESPACE>"
kind = "<KIND>"
emulatorHost = "<EMULATOR_HOST>:<EMULATOR_PORT>"
)
func main() {
ctx := context.Background()
// Create the Cloud Datastore client
remoteClient, err := datastore.NewClient(ctx, projectId, option.WithGRPCConnectionPool(50))
if err != nil {
fmt.Fprintf(os.Stderr, "Could not create remote datastore client: %v \n", err)
}
// Create the local Datastore Emulator client
o := []option.ClientOption{
option.WithEndpoint(emulatorHost),
option.WithoutAuthentication(),
option.WithGRPCDialOption(grpc.WithInsecure()),
option.WithGRPCConnectionPool(50),
}
localClient, err := datastore.NewClient(ctx, projectId, o...)
if err != nil {
fmt.Fprintf(os.Stderr, "Could not create local datastore client: %v \n", err)
}
// Create the query
q := datastore.NewQuery(kind).Namespace(namespace)
//Run the query and handle the received entities
start := time.Now() // This is just to calculate the rate
for it, i := remoteClient.Run(ctx, q), 1; ; i++ {
x := &arbitraryEntity{}
// Get the entity
key, err := it.Next(x)
if err == iterator.Done {
break
}
if err != nil {
fmt.Fprintf(os.Stderr, "Error retrieving entity: %v \n", err)
}
// Insert the entity into the emulator
_, err = localClient.Put(ctx, key, x)
if err != nil {
fmt.Fprintf(os.Stderr, "Error saving entity: %v \n", err)
}
// Print stats
go fmt.Fprintf(os.Stdout, "\rCopied %v entities. Rate: %v/s", i, i/int(time.Since(start).Seconds()))
}
fmt.Fprintln(os.Stdout)
}
// Declare a struct capable of handling any type of entity.
// It implements the PropertyLoadSaver interface
type arbitraryEntity struct {
properties []datastore.Property
}
func (e *arbitraryEntity) Load(ps []datastore.Property) error {
e.properties = ps
return nil
}
func (e *arbitraryEntity) Save() ([]datastore.Property, error) {
return e.properties, nil
}
有了这个,我得到的速率约为700个实体/秒,但是根据您拥有的实体,它的变化可能很大。
请勿设置DATASTORE_EMULATOR_HOST
env变量,因为脚本是手动创建与本地仿真器的连接,并且您希望库自动连接到Cloud Datastore。
可以大大改善脚本:远程和本地都使用GRPC,因此您可以使用一些原始魔术来避免对消息进行编码/解码。使用批处理上传也将有所帮助,以及使用Go的并发技巧。您甚至可以通过编程方式获取名称空间和种类,因此您无需为每个实体都运行它。
但是,我认为这个简单的概念证明可以帮助您了解如何开发自己的工具来运行导入。
答案 1 :(得分:1)
数据存储模拟器现在支持导入和导出:
导入:
curl -X POST localhost:8081/v1/projects/[PROJECT_ID]:import \
-H 'Content-Type: application/json' \
-d '{"input_url":"[ENTITY_EXPORT_FILES]"}'
导出:
curl -X POST localhost:8081/v1/projects/[PROJECT_ID]:export \
-H 'Content-Type: application/json' \
-d '{"output_url_prefix":"EXPORT_DIRECTORY"}'
https://cloud.google.com/datastore/docs/tools/emulator-export-import