下面是一个最小Python示例,显示将实体添加到NDB,然后删除所有实体。
然而,尽管实体似乎已被删除,但Datastore Viewer
仍会显示它们 - 即使在我刷新Memcache.
我应该更改哪些内容以便删除NDB实体?
我的代码:
from google.appengine.ext import ndb
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from models import Data
KEY = "fastsimon"
datum_key = dict()
class InvalidHandler(webapp.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write('Invalid entry')
class GetHandler(webapp.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write('Get!\n')
name = self.request.get('name')
out_str = "Should not be seen"
try:
ancestor_key = datum_key[name]
qry = Data.owner_query(ancestor_key)
data = qry.fetch()
out_str = data[-1].value
except KeyError:
out_str = "None"
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write(out_str)
class EndHandler(webapp.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write('End!')
qry = Data.query().iter(keys_only=True)
print "before delete"
list_of_keys = list()
for q in qry:
print "ndb.Key('Datum',q):",ndb.Key('Datum',q.integer_id())
list_of_keys.append(ndb.Key('Datum',q.integer_id()))
print "list_of_keys:",list_of_keys
ndb.delete_multi(list_of_keys)
print "after delete"
for q in qry:
print "ndb.Key('Datum',q):",ndb.Key('Datum',q.integer_id())
class SetHandler(webapp.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write('Set!\n')
name=self.request.get('name')
data = Data(parent=ndb.Key("Datum", KEY),
name=name,
value=self.request.get('value'))
print "data:",data
ret_key = data.put()
datum_key[name] = ret_key
def main():
application = webapp.WSGIApplication([
('/get', GetHandler),
('/set', SetHandler),
('/end', EndHandler)],
debug=False)
global app
app = application
run_wsgi_app(app)
if __name__ == 'main':
main()
models.py:
from google.appengine.ext import ndb
class Data(ndb.Model):
name = ndb.StringProperty() # Upto 500 characters
value = ndb.TextProperty(required=True) # Unlimited length
@classmethod
def owner_query(cls, parent_key):
return cls.query(ancestor=parent_key).order(cls.name)
我采取的步骤:
调试行是:
data: Data(key=Key('Datum', 'fastsimon', 'Data', None), name=u'a', value=u'1')
INFO 2016-10-20 11:29:34,213 module.py:788] default: "GET /set?name=a&value=1 HTTP/1.1" 200 5
data: Data(key=Key('Datum', 'fastsimon', 'Data', None), name=u'b', value=u'2')
INFO 2016-10-20 11:29:50,442 module.py:788] default: "GET /set?name=b&value=2 HTTP/1.1" 200 5
before delete
ndb.Key('Datum',q): Key('Datum', 4661104668049408)
ndb.Key('Datum',q): Key('Datum', 5787004574892032)
list_of_keys: [Key('Datum', 4661104668049408), Key('Datum', 5787004574892032)]
after delete
INFO 2016-10-20 11:30:04,125 module.py:788] default: "GET /end HTTP/1.1" 200 4
但是,当我转到数据存储区查看器并按下Flush Memcache时,我仍然看到那里的实体:
我应该更改哪些内容以便删除NDB实体?
答案 0 :(得分:1)
In general you need to be careful with your queries when you use ancestries for your entities - queries with and without ancestor keys specified will produce different (non-overlapping) results. See Ancestor Queries
The root cause of your problem is that the keys you're building in the list_of_keys
to be deleted do not match the original keys if the respective entities have ancestors, thus what's passed to ndb.delete_multi
may miss some of the keys you intend to delete.
ndb.Key('Datum',q.integer_id())
produces a key for an entity without an ancestor which will not match the q
key if q
is the key of an entity with an ancestor.
A simple solution would be to not convert the keys you want to delete, instead pass them directly to ndb.delete_multi()
, for example you could simply do ndb.delete_multi([key for key in qry])
instead of ndb.delete_multi(list_of_keys)
答案 1 :(得分:1)
根据@DanCornilescu的优秀建议,我更改了EndHandler
的代码,它现在删除了像冠军一样的实体。
代码:
from google.appengine.ext import ndb
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from models import Data
KEY = "fastsimon"
datum_key = dict()
class InvalidHandler(webapp.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write('Invalid entry')
class GetHandler(webapp.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write('Get!\n')
name = self.request.get('name')
out_str = "Should not be seen"
try:
ancestor_key = datum_key[name]
qry = Data.owner_query(ancestor_key)
data = qry.fetch()
out_str = data[-1].value
except KeyError:
out_str = "None"
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write(out_str)
class EndHandler(webapp.RequestHandler):
def show_entities(self):
for q in datum_key.values():
k = ndb.Key('Datum', 'fastsimon', 'Data',q.integer_id())
print "entity for",k,"=>", ndb.Key('Datum', 'fastsimon', 'Data',q.integer_id()).get()
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write('End!')
print "datum_key.values():",datum_key.values()
print "before delete"
self.show_entities()
ndb.delete_multi(datum_key.values())
print "after delete"
self.show_entities()
class SetHandler(webapp.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write('Set!\n')
name=self.request.get('name')
data = Data(parent=ndb.Key("Datum", KEY),
name=name,
value=self.request.get('value'))
ret_key = data.put()
datum_key[name] = ret_key
print "data:",data
def main():
application = webapp.WSGIApplication([
('/get', GetHandler),
('/set', SetHandler),
('/end', EndHandler)],
debug=False)
global app
app = application
run_wsgi_app(app)
if __name__ == 'main':
main()
调试行:
data: Data(key=Key('Datum', 'fastsimon', 'Data', 4943129400573952), name=u'z', value=u'55')
INFO 2016-10-20 13:40:17,008 module.py:788] default: "GET /set?name=z&value=55 HTTP/1.1" 200 5
data: Data(key=Key('Datum', 'fastsimon', 'Data', 6069029307416576), name=u'x', value=u'88')
INFO 2016-10-20 13:40:28,556 module.py:788] default: "GET /set?name=x&value=88 HTTP/1.1" 200 5
datum_key.values(): [Key('Datum', 'fastsimon', 'Data', 4943129400573952), Key('Datum', 'fastsimon', 'Data', 6069029307416576)]
before delete
entity for Key('Datum', 'fastsimon', 'Data', 4943129400573952) => Data(key=Key('Datum', 'fastsimon', 'Data', 4943129400573952), name=u'z', value=u'55')
entity for Key('Datum', 'fastsimon', 'Data', 6069029307416576) => Data(key=Key('Datum', 'fastsimon', 'Data', 6069029307416576), name=u'x', value=u'88')
after delete
entity for Key('Datum', 'fastsimon', 'Data', 4943129400573952) => None
entity for Key('Datum', 'fastsimon', 'Data', 6069029307416576) => None
INFO 2016-10-20 13:40:40,517 module.py:788] default: "GET /end HTTP/1.1" 200 4
并且数据存储区查看器不显示任何实体。