带自数据的MongoDB条件查询

带自数据的MongoDB条件查询,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,假设集合中有4个用户 > db.users.find().pretty() { "_id" : ObjectId("5d369b451b48d91cba76c618"), "user_id" : 1, "final_score" : 65, "max_score" : 15, "min_score" : 15, } { "_id" : ObjectId("5d369b451b48d91cba76c619"), "user_id" :

假设集合中有4个用户

> db.users.find().pretty()
{
    "_id" : ObjectId("5d369b451b48d91cba76c618"),
    "user_id" : 1,
    "final_score" : 65,
    "max_score" : 15,
    "min_score" : 15,
}
{
    "_id" : ObjectId("5d369b451b48d91cba76c619"),
    "user_id" : 2,
    "final_score" : 70,
    "max_score" : 15,
    "min_score" : 15,
}
{
    "_id" : ObjectId("5d369b451b48d91cba76c61a"),
    "user_id" : 3,
    "final_score" : 60,
    "max_score" : 15,
    "min_score" : 15,
}
{
    "_id" : ObjectId("5d369b451b48d91cba76c61b"),
    "user_id" : 4,
    "final_score" : 83,
    "max_score" : 15,
    "min_score" : 15,
}
我想提取满足以下条件的用户

  • final\u score
    =
    user\u id=3
    final\u score
    +
    每个文档的最大得分

  • final_score
    这里的困难在于,您需要运行两个单独的管道(一个用于获取用户3的值,另一个用于过滤所有文档)。在聚合框架中,您可以使用运算符来实现这一点,该运算符允许您运行多个管道,然后在后续步骤中继续处理数据。要比较可以使用的数据并获得原始形状,需要使用和将嵌套数组转换为单独的文档


    根据您的描述,我想您已经知道
    user3
    的分数是
    60

    在这种情况下:

    db.collection.aggregate([
      {
        $addFields: {
          match: {
            $and: [
              {
                $gte: [
                  "$final_score",
                  {
                    $subtract: [
                      60,
                      "$min_score"
                    ]
                  }
                ]
              },
              {
                $lte: [
                  "$final_score",
                  {
                    $add: [
                      60,
                      "$max_score"
                    ]
                  }
                ]
              }
            ]
          }
        }
      },
      {
        $match: {
          match: true
        }
      },
      {
        $project: {
          match: 0
        }
      }
    ])
    

    正是我想要的。谢谢:)为了提高性能,我应该只在
    final_score
    字段上触发索引吗?@Hide不确定它是否能产生任何影响,您可以尝试使用和不使用index@Hide您可以通过索引
    user\u id
    以某种方式提高性能。您是否认识最终得分为
    id=3的用户,或者只知道
    user\u id
    ?在任何情况下,都无所谓。(我可以单独查询)但我必须关注性能。
    db.users.find({
        'final_score': {
            '$lte': '60 + this.max_score',
            '$gte': '60 - this.min_score'
        }
    })
    
    db.users.aggregate([
        {
            $facet: {
                user3: [
                    { $match: { user_id: 3 } }
                ],
                docs: [
                    { $match: {} }
                ]
            }
        },
        {
            $addFields: {
                user3: { $arrayElemAt: [ "$user3", 0 ] }
            }
        },
        {
            $project: {
                docs: {
                    $filter: {
                        input: "$docs",
                        cond: {
                            $and: [
                                { $lte: [ "$$this.final_score", { $add: [ "$user3.final_score", "$$this.max_score" ] } ] },
                                { $gte: [ "$$this.final_score", { $subtract: [ "$user3.final_score", "$$this.max_score" ] } ] },
                            ]
                        }
                    }
                }
            }
        },
        {
            $unwind: "$docs"
        },
        {
            $replaceRoot: {
                newRoot: "$docs"
            }
        }
    ])
    
    db.collection.aggregate([
      {
        $addFields: {
          match: {
            $and: [
              {
                $gte: [
                  "$final_score",
                  {
                    $subtract: [
                      60,
                      "$min_score"
                    ]
                  }
                ]
              },
              {
                $lte: [
                  "$final_score",
                  {
                    $add: [
                      60,
                      "$max_score"
                    ]
                  }
                ]
              }
            ]
          }
        }
      },
      {
        $match: {
          match: true
        }
      },
      {
        $project: {
          match: 0
        }
      }
    ])