如何在向MongoDB集合中插入文档时处理文档大小超过16MB的错误。

7

请问有没有人能够建议如何在将文档插入MongoDB集合时处理文档大小超过16MB的错误。我得到了一些解决方案,例如使用GridFS。通过使用GridFS可以解决此问题,但是我需要不使用GridFS的解决方案。是否有办法使文档变小或分割成子文档。如果有,我们怎么实现呢?

from pymongo import MongoClient

conn = MongoClient("mongodb://sample_mongo:27017")
db_conn = conn["test"]
db_collection = db_conn["sample"]

# the size of record is 23MB

record = { \
    "name": "drugs",
    "collection_id": 23,
    "timestamp": 1515065002,
    "tokens": [], # contains list of strings
    "tokens_missing": [], # contains list of strings
    "token_mapping": {} # Dictionary contains transformed tokens
 }

db_collection.insert(record, check_keys=False)

我遇到了错误DocumentTooLarge: BSON document too large。在MongoDB中,最大的BSON文档大小为16兆字节。

  File "/usr/local/lib/python2.7/dist-packages/pymongo-3.5.1-py2.7-linux-x86_64.egg/pymongo/collection.py", line 2501, in insert
check_keys, manipulate, write_concern)
  File "/usr/local/lib/python2.7/dist-packages/pymongo-3.5.1-py2.7-linux-x86_64.egg/pymongo/collection.py", line 575, in _insert
check_keys, manipulate, write_concern, op_id, bypass_doc_val)
  File "/usr/local/lib/python2.7/dist-packages/pymongo-3.5.1-py2.7-linux-x86_64.egg/pymongo/collection.py", line 556, in _insert_one
check_keys=check_keys)
  File "/usr/local/lib/python2.7/dist-packages/pymongo-3.5.1-py2.7-linux-x86_64.egg/pymongo/pool.py", line 482, in command
self._raise_connection_failure(error)
  File "/usr/local/lib/python2.7/dist-packages/pymongo-3.5.1-py2.7-linux-x86_64.egg/pymongo/pool.py", line 610, in _raise_connection_failure
raise error
  DocumentTooLarge: BSON document too large (22451007 bytes) - the connected server supports BSON document sizes up to 16793598 bytes.

1
欢迎来到Stack Overflow,请在提问时更具体一些:你用什么代码尝试过?(我投反对票是因为没有代码 / 你期望得到什么结果? / 你遇到了什么错误? **需要帮助请查看 "如何提问"**。 - Hille
1
Hille 更新了我尝试的代码并指出了错误。谢谢。 - Thrisundar Reddy J
找出使文档变得如此庞大的字段是什么(tokens、tokens_missing?),将其存储在一个单独的集合中,作为一个包含对原始文档引用的文档。 - Andriy Simonov
2个回答

2
最大的BSON文档大小为16兆字节。为了存储超过最大大小的文档,MongoDB提供了GridFS API。 GridFS是一种用于存储和检索超过16MB BSON文档大小限制的文件的规范。GridFS通过将大型文档分成部分或块来存储它。每个块都存储在单独的文档中。GridFS块的默认大小为255 KB。GridFS使用两个集合来存储文件。一个集合存储文件块,另一个集合存储文件元数据。

不使用GridFS,我们不能处理这个问题吗?通过维护文档之间的引用,即将文档拆分为子文档,并通过ObjectIds在文档之间建立引用,从而减小文档大小。请告诉我您是否明白我的意思。我已经阅读了关于文档之间关系的URL https://studytonight.com/mongodb/relationships-in-mongodb,但我没有清楚如何实现。谢谢。 - Thrisundar Reddy J
你可以将文档拆分为多个文档,并将其存储在多个集合中,前提是每个文档的大小都小于16MB。GridFS是mongoDB提供的解决方案,用于存储更大的文档而无需手动拆分。在任何情况下,文档都会被手动或通过Mongo拆分。如果我们手动拆分,则需要维护文档之间的关系,而在GridFS中,这由MongoDB来处理。有关GridFS示例,请参考此帖子-http://api.mongodb.com/python/current/examples/gridfs.html - Clement Amarnath

1
快速回答是不行的,你不能绕过16 MB BSON大小限制。如果你达到了这个限制,你需要探索其他选择,比如GridFS或者为你的文档设计不同的架构。
我会先提出一系列问题来确定你设计的重点,比如:
你有名为 tokenstokens_missingtoken_mapping 的字段。我想象这些字段单独很大,将它们全部放入一个文档中会使其超过16MB。是否可以将此文档拆分为三个集合?
你的应用程序访问模式是什么?您需要一直访问哪个字段?哪个字段您不经常访问?您可以根据这些模式将文档拆分为不同的集合。
请记住需要对文档进行索引,因为MongoDB的性能与支持查询的良好索引密切相关。您无法在单个索引中索引两个数组。多键索引中有更多信息。
如果需要在查询中组合所有相关数据,则MongoDB 3.2及更高版本提供了$lookup运算符,类似于SQL的左外连接。
与SQL的正常形式模式设计不同,MongoDB的模式设计基于您应用程序的访问模式。16 MB的限制存在是为了让您知道设计可能不是最佳的,因为这样大的文档会对性能、更新等产生不利影响。通常情况下,拥有许多小文档比拥有少量巨型文档更好。
更多示例可以在数据模型设计数据模型示例和模式中找到。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接