最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【已解决】PyMongo中GridFS的exists始终检测不到文件已存在

MongoDB crifan 3438浏览 0评论

折腾:

【已解决】用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>&gt;&gt;&gt; fs.exists(file_id)
&gt;&gt;&gt; fs.exists({"_id":file_id})
&gt;&gt;&gt; fs.exists(_id=file_id)
&gt;&gt;&gt; fs.exists({"filename": "mike.txt"})
&gt;&gt;&gt; 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的文档以后能及时更新啊。

转载请注明:在路上 » 【已解决】PyMongo中GridFS的exists始终检测不到文件已存在

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
82 queries in 0.187 seconds, using 22.10MB memory