这应该是一个相当普遍的要求,也是一个简单的过程:将数据批量上传到appengine数据存储区。
但是,stackoverflow(下面的链接*)中提到的旧解决方案似乎都不再有效。 bulkloader方法是使用DB API上传到数据存储区时最合理的解决方案,但不能与NDB API一起使用
现在,批量加载器方法似乎已被弃用,旧文档中仍然存在的旧链接导致页面错误。这是一个例子
https://developers.google.com/appengine/docs/python/tools/uploadingdata
上述链接仍显示在此页面上:https://developers.google.com/appengine/docs/python/tools/uploadinganapp
现在批量加载数据的推荐方法是什么?
两个可行的替代方案似乎是1)使用remote_api或2)将CSV文件写入GCS存储桶并从中读取。有没有人有成功使用这两种方法的经验?
任何指针都将非常感激。谢谢!
[*以下链接提供的解决方案不再有效]
[1] how does one upload data in bulk to a google appengine datastore?
答案 0 :(得分:9)
方法1:使用remote_api
如何:编写 bulkloader.yaml 文件并使用终端中的“ appcfg.py upload_data ”命令直接运行 我不推荐这种方法有以下几个原因:1。巨大的延迟2.不支持NDB
方法2:GCS并使用mapreduce
将数据文件上传到GCS:
使用“storage-file-transfer-json-python”github项目(chunked_transfer.py)将文件从本地系统上传到gcs。 确保从应用引擎管理控制台生成正确的“client-secrets.json”文件。
<强>的MapReduce:强>
使用&#34; appengine-mapreduce&#34; github项目。复制&#34; mapreduce&#34;文件夹到项目顶级文件夹。
将以下行添加到app.yaml文件中:
includes:
- mapreduce/include.yaml
以下是您的main.py文件
import cgi
import webapp2
import logging
import os, csv
from models import DataStoreModel
import StringIO
from google.appengine.api import app_identity
from mapreduce import base_handler
from mapreduce import mapreduce_pipeline
from mapreduce import operation as op
from mapreduce.input_readers import InputReader
def testmapperFunc(newRequest):
f = StringIO.StringIO(newRequest)
reader = csv.reader(f, delimiter=',')
for row in reader:
newEntry = DataStoreModel(attr1=row[0], link=row[1])
yield op.db.Put(newEntry)
class TestGCSReaderPipeline(base_handler.PipelineBase):
def run(self, filename):
yield mapreduce_pipeline.MapreducePipeline(
"test_gcs",
"testgcs.testmapperFunc",
"mapreduce.input_readers.FileInputReader",
mapper_params={
"files": [filename],
"format": 'lines'
},
shards=1)
class tempTestRequestGCSUpload(webapp2.RequestHandler):
def get(self):
bucket_name = os.environ.get('BUCKET_NAME',
app_identity.get_default_gcs_bucket_name())
bucket = '/gs/' + bucket_name
filename = bucket + '/' + 'tempfile.csv'
pipeline = TestGCSReaderPipeline(filename)
pipeline.with_params(target="mapreducetestmodtest")
pipeline.start()
self.response.out.write('done')
application = webapp2.WSGIApplication([
('/gcsupload', tempTestRequestGCSUpload),
], debug=True)
要记住:
方法3:GCS和GCS客户端库
将以下代码添加到应用程序main.py文件中。
import cgi
import webapp2
import logging
import jinja2
import os, csv
import cloudstorage as gcs
from google.appengine.ext import ndb
from google.appengine.api import app_identity
from models import DataStoreModel
class UploadGCSData(webapp2.RequestHandler):
def get(self):
bucket_name = os.environ.get('BUCKET_NAME',
app_identity.get_default_gcs_bucket_name())
bucket = '/' + bucket_name
filename = bucket + '/tempfile.csv'
self.upload_file(filename)
def upload_file(self, filename):
gcs_file = gcs.open(filename)
datareader = csv.reader(gcs_file)
count = 0
entities = []
for row in datareader:
count += 1
newProd = DataStoreModel(attr1=row[0], link=row[1])
entities.append(newProd)
if count%50==0 and entities:
ndb.put_multi(entities)
entities=[]
if entities:
ndb.put_multi(entities)
application = webapp2.WSGIApplication([
('/gcsupload', UploadGCSData),
], debug=True)
答案 1 :(得分:3)
远程API方法,如链接[1]中所示,仍然可以正常工作 - 尽管如果你有超过几百行,它会非常慢。
我已经成功地将GCS与MapReduce框架结合使用来下载而不是上传数据存储区的内容,但原则应该是相同的。请参阅mapreduce documentation:实际上您只需要映射器步骤,因此您可以定义一个简单的函数,该函数接受CSV中的行并从该数据创建数据存储区实体。
答案 2 :(得分:1)
截至2018年,最好的方法是使用the new import/export capability。
答案 3 :(得分:0)
你们中的一些人可能在我的情况下:我无法使用数据存储区的导入/导出实用程序,因为我的数据需要在进入数据存储区之前进行转换。
我最终使用 apache-beam(google cloud dataflow)。
你只需写几行&#34; beam&#34;代码
PCollection
个字符串,PCollection
数据存储区实体),有关具体用例,请参阅How to speedup bulk importing into google cloud datastore with multiple workers?。
我能够以每秒800个实体的速度写入我的数据存储区,其中包含5名工作人员。这使我能够在大约5个小时内完成导入任务(包含1600万行)。如果你想让它更快,请使用更多的工人:D