折腾:
【已解决】用Python去连接本地mongoDB去用GridFS保存文件
期间,需要继续去调试delete删除文件。
然后就去用代码:
<code># test file delete # fileIdToDelete = "5abc96dfa4bc715f473f0297" # fileIdToDelete = "5abc9525a4bc715e187c6d6d" # fileIdToDelete = "ObjectId('5abc96dfa4bc715f473f0297')" # fileIdToDelete = 'ObjectId("5abc8d77a4bc71563222d455")' fileIdToDelete = '5abc8d77a4bc71563222d455' if fsCollection.exists(fileIdToDelete): fsCollection.delete(fileIdToDelete) logging.info("delete file id %s ok", fileIdToDelete) else: logging.warning("Can not find file to delete for id=%s", fileIdToDelete) </code>
exists始终无法正常执行,无法进入到delete的代码。
pymongo gridfs exists not work
mongodb gridfs “no file” error with python – Stack Overflow
gridfs – Tools for working with GridFS — PyMongo 2.7rc1 documentation
gridfs – Tools for working with GridFS — PyMongo 3.0.2 documentation
django – Querying by “_id” doesn’t return file in MongoDB in Python, using PyMongo – Stack Overflow
我靠真是坑爹,貌似需要再引入:ObjectId才可以?
但是人家说的是:pymongo versions < 2.2
而我这里是:3.6的版本,应该不需要啊
然后去:
<code>from pymongo.objectid import ObjectId from pymongo import objectid </code>
也的确会报错:
那去试试find或find_one:如果正常,那么说明exists不正常
结果也是找不到:
再试试:
<code># fileIdToDelete = 'ObjectId("5abc8d77a4bc71563222d455")' fileIdToDelete = '5abc8d77a4bc71563222d455' foundFile = fsCollection.find_one({"_id": fileIdToDelete}) logging.info("foundFile=%s", foundFile) </code>
结果:也不行。
直接用find,找到一个文件:
拷贝出其中的_id
结果拷贝出来的值是:
5abc43a4a4bc712159a35cd9
而不是ObjectId的对象
那先去用这个id去搜索试试,看看能否找到:
然后确实是可以的:
<code># foundFile = fsCollection.find_one({"_id": fileIdToDelete}) foundFile = fsCollection.find_one() logging.info("foundFile=%s", foundFile) fileIdToDelete = foundFile._id logging.info("fileIdToDelete=%s", fileIdToDelete) if fsCollection.exists(fileIdToDelete): fsCollection.delete(fileIdToDelete) logging.info("delete file id %s ok", fileIdToDelete) else: logging.warning("Can not find file to delete for id=%s", fileIdToDelete) </code>
结果:
<code>2018/03/29 04:05:11 LINE 105 INFO fileIdToDelete=5abc43a4a4bc712159a35cd9 2018/03/29 04:06:23 LINE 109 INFO delete file id 5abc43a4a4bc712159a35cd9 ok </code>
真是诡异了。
为何此处我去mongo的客户端中
db.fs.files.find().pretty()
找到的别的某个的file的id,却找不到???
注意到了:
此处的file的id是ObjectID的实例,而不是字符串:
所以才能删除掉。
所以要去想办法,找到到底如何引入,导入,找到,ObjectId这个类
grid_file – Tools for representing files stored in GridFS — PyMongo 3.6.1 documentation
-》
objectid – Tools for working with MongoDB ObjectIds — PyMongo 3.6.1 documentation
才看到是:
bson.objectid.ObjectId
<code>from bson.objectid import ObjectId </code>
就可以了:
注意到:
fileIdToDelete是str
fileObjectIdToDelete是ObjectId
然后即可正常删除了:
【总结】
此处,gridfs的官网文档:
gridfs – Tools for working with GridFS — PyMongo 3.6.1 documentation
还是有点坑的,对于:
exists(document_or_id=None, session=None, **kwargs)
来说,没有说明:
document_or_id
是个特殊的ObjectId的这个类的实例,而其例子:
<code>>>> fs.exists(file_id) >>> fs.exists({"_id":file_id}) >>> fs.exists(_id=file_id) >>> fs.exists({"filename": "mike.txt"}) >>> fs.exists(filename="mike.txt") </code>
很容易让人误解就是普通的_id的值的字符串,比如:
“5abc96dfa4bc715f473f0297”
或:
“ObjectId(‘5abc96dfa4bc715f473f0297’)”
搞得半天也无法正常执行,找不到本来已存在的文件。
幸亏:
django – Querying by “_id” doesn’t return file in MongoDB in Python, using PyMongo – Stack Overflow
中解释的:
pymongo:
2.2版本之前:
<code>from pymongo.objectid import ObjectId </code>
2.2版本之后:
<code>from bson.objectid import ObjectId </code>
然后才能用于exists:
<code>fileIdToDelete = ‘5abc8d77a4bc71563222d455' fileObjectIdToDelete = ObjectId(fileIdToDelete) if fsCollection.exists(fileObjectIdToDelete): fsCollection.delete(fileObjectIdToDelete) </code>
并且注意到作者是2012年,6年前就回复了该答案,结果此处pymongo在6年后,都没有及时更新此内容,真是醉了。希望mongodb的文档以后能及时更新啊。