使用默认值和嵌套对象时,猫鼬查询变慢

时间:2018-08-22 23:18:50

标签: mongodb mongoose mongoose-schema

我有一个用户文档,其中包含与页面上的组件有关的多层嵌套对象。

"featuredImage": {
                    "config": {
                        "style": {
                            "margin": {
                                "right": 0,
                                "left": 0,
                                "top": 0,
                                "bottom": 30
                            },
                            "background": "rgba(0, 0, 0, 0)"
                        },
                        "class": "ss-article-featured-image"
                    }
                },
                "info": {
                    "date": {
                        "config": {
                            "style": {
                                "margin": {
                                    "right": 5,
                                    "left": 5,
                                    "top": 0,
                                    "bottom": 0
                                },
                                "fontWeight": "normal",
                                "fontSize": 16,
                                "background": "rgba(0, 0, 0, 0)",
                                "color": "inherit"
                            },
                            "show": true,
                            "class": "ss-article-date"
                        }
                    },
...
...

此用户文档上可能有〜50个组件(嵌套对象)(平均文档大小为10kb)。

我正在使用Mongoose的“默认值”来自动填充内容(例如0,或者未明确提供的字符串)。

当我查询该用户时,查询速度很快,我可以通过ID查找它,但是即使对本地数据库本地主机来说,对文档结果的计时最终也要> 10ms。 当我在Heroku上(从连接的数据库中)执行此操作时,大约需要30ms-100ms。

当我使用lean()时,查询要快得多:〜5ms

(仅供参考,我只是将查询调用包装在console.time中以对其计时)

.lean()会清除默认值,而我依赖默认值来渲染内容,因此这并不是一个选择。

关于此文档样式,是否会导致猫鼬的此类开销?是默认值吗?是否存在这么多嵌套对象的事实?该文档本身并不大,我的用户的平均文档大小为10kb。

{p1}查找

50毫秒非常糟糕。但这似乎是导致问题的文档的“大小”或“样式”。同样,该文档也不大。

有人可以在这里亮点吗?

1 个答案:

答案 0 :(得分:0)

对于大型对象(例如,您的(10K))和使用默认对象,没有什么要考虑的。在这种情况下,Mongoose非常繁琐,因为它必须为您提供从模式中定义的Mongoose模型,该模型是在从MongoDB检索结果后使用默认值等处理的。

这就是为什么您看到并使用lean()的原因,因为它removes that overhead and returns just plain objects with no mongoose sugar around them。由于您依赖默认值,因此这也会使您付出代价。

建议不要返回完整的对象,而只返回所需的字段。我认为您几乎不需要整个10K文档。

Docs on how to select and return partial (specific fields only) result

有关如何更新basically just using $set局部模型的文档

另一种建议是,尽管有些激进的做法是考虑让像您这样的情况降级到mongoDB本机驱动程序并使用它,因为与Mongoose相比,在像您这样的大型对象上这样做要快得多。