C#Mongodb通过查找进行搜索非常昂贵

问题描述

我是MongoDb的新手,并且遇到性能问题。

我有2个收藏集,“ A”和“ B”
“ A”具有一个列表,其_id为“ B”(例如50个元素)

我要实现的是通过对“ B”的查询查询“ A”。

示例
假设A是神奇宝贝,B是Moves。
我想找到所有动力大于等于30的宠物小精灵

我所做的就是这样:

db.collection("pokemon")
    .aggregate()
    .lookup("Moves","moves.move_id","_id","full_moves")
    .match({ $gte: { "full_moves.power": 30 }})

(这里的代码一个示例,不是C#,但我在C#中也做同样的事情)

通过我的结构,它可以正常工作,我得到了想要的。
但是性能太差了。
如果我用Skip(n)和Limit(n + 20)限制结果,则需要2秒来执行聚合。
如果我不这样做,则大约需要28秒来执行完整查找。

我做的对吗?还有其他办法吗?

我知道我应该把文档“ B”作为“ A”的子文档,但是“ B”很大,并且“ A”与“ B”有50种关系,我认为这不是一条合适的路径。

谢谢


修改
这里的Pkm文档结构(不是确切的,我只是在玩弄以了解mongodb)

口袋妖怪

{
    "_id": ObjectId(''),"abilities": [
        {
            //Simple object with 3 props
        }
    ],"experience": 64,"forms": [
        {
            //Simple object with 5 props
        }
    ],"height": 7,"id": 1,"is_default": true,"moves": [ //a pokemon can have like 50 moves
        {
            //Complex object with like 20 properties,some are Array but for search purpose I use only not nested properties like power,name etc
        }
    ],"name": "bulbasaur","stats": {
        "hp": 0,"attack": 0,"defense": 0,"special-attack": 0,"special-defense": 0,"speed": 0
    },"types": [
        {
        //simple object with 2 properties
        }
    ],"weight": 50
}

我还使用说明在MongodbCompass中运行过滤器,它说对于集合来说,查询操作({“ moves.move.power”:{$ gte:30}}花费了4毫秒

{
 "stage": "FETCH","nReturned": 942,"executionTimeMillisEstimate": 4,"works": 12179,"advanced": 942,"needTime": 11236,"needYield": 0,"saveState": 12,"restoreState": 12,"iSEOF": 1,"docsexamined": 942,"alreadyHasObj": 0
}

那么可能这里的问题是这些数据的表现形式?
我将C#最新驱动程序用于mongodb,并将清单BsonDocument用作清单,我使用LinQ“ ToList()”

解决方法

此聚合查询可能会更好一些,因为过滤是在联接端进行的。

db.pokemon.aggregate([
   {
      $lookup:
         {
           from: "Moves",let: { move_id: "$moves.move_id" },pipeline: [
              { $match:
                 { $expr:
                    { $and:
                       [
                         { $gte: [ "$power",30 ] },{ $eq: [ "$_id","$$move_id" ] }
                       ]
                    }
                 }
              }
           ],as: "full_moves"
         }
    }
])

然后,您还可以在Moves的{​​{1}}集合上添加索引,这将使索引效率更高。

但是,如果这些举动属于口袋妖怪,那么您可能需要重新考虑重新建模文档以减少关联。然后将动作放在口袋妖怪文档中。