【问题标题】:Match multiple values in MongoDB with one query in pymongo将 MongoDB 中的多个值与 pymongo 中的一个查询匹配
【发布时间】:2020-09-15 15:46:20
【问题描述】:

我有一个集合测试,它具有以下值,我必须根据“值”字段从中获取文档,我可以从下面的给定查询中轻松获取。

db.getCollection('test').find({"value" : 100})

但真正的问题是我有“值”字段列表,例如 [100,104,200152,.......] 这个列表可能真的很长,我希望我的结果采用以下给定格式,以减少 mongo 查询的数量,因为这需要太多时间,如果包含“值”的列表太大,那么我必须执行多个 mongo 查询来获取所有的记录。

{100:[
    /* 1 */

    {
        "_id" : "C1",
        "value" : 100,
        "lastUpdatedTime" : ISODate("2019-11-04T00:00:00.000Z"),
        "timetaken" : 3.0
    }

    /* 2 */
    {
        "_id" : "C2",
        "value" : 100,
        "lastUpdatedTime" : ISODate("2019-11-04T00:00:00.000Z"),
        "timetaken" : 3.0
    }

    /* 3 */
    {
        "_id" : "C3",
        "value" : 100,
        "lastUpdatedTime" : ISODate("2019-11-04T00:00:00.000Z"),
        "timetaken" : 3.0
    }

    /* 4 */
    {
        "_id" : "C4",
        "value" : 100,
        "lastUpdatedTime" : ISODate("2019-11-04T00:00:00.000Z"),
        "timetaken" : 3.0
    }

    /* 5 */
    {
        "_id" : "CO",
        "value" : 100,
        "lastUpdatedTime" : ISODate("2019-11-04T00:00:00.000Z"),
        "timetaken" : 3.0
    }

    /* 6 */
    {
        "_id" : "DD",
        "value" : 100,
        "lastUpdatedTime" : ISODate("2019-11-04T00:00:00.000Z"),
        "timetaken" : 3.0
    }

    /* 7 */
    {
        "_id" : "EX",
        "value" : 100,
        "lastUpdatedTime" : ISODate("2019-11-04T00:00:00.000Z"),
        "timetaken" : 3.0
    }],

104:

    [{
        "_id" : "AU",
        "value" : 104,
        "lastUpdatedTime" : ISODate("2019-11-04T00:00:00.000Z"),
        "timetaken" : 3.0
    }],
200152:

    [
    {
        "_id" : "GenFile",
        "value" : 200152,
        "lastUpdatedTime" : ISODate("2019-11-04T00:00:00.000Z"),
        "timetaken" : 3.0
    }
    ]

数据库

/* 1 */
{
    "_id" : "AU",
    "value" : 104,
    "lastUpdatedTime" : ISODate("2019-11-04T00:00:00.000Z"),
    "timetaken" : 3.0
}

/* 2 */
{
    "_id" : "C1",
    "value" : 100,
    "lastUpdatedTime" : ISODate("2019-11-04T00:00:00.000Z"),
    "timetaken" : 3.0
}

/* 3 */
{
    "_id" : "C2",
    "value" : 100,
    "lastUpdatedTime" : ISODate("2019-11-04T00:00:00.000Z"),
    "timetaken" : 3.0
}

/* 4 */
{
    "_id" : "C3",
    "value" : 100,
    "lastUpdatedTime" : ISODate("2019-11-04T00:00:00.000Z"),
    "timetaken" : 3.0
}

/* 5 */
{
    "_id" : "C4",
    "value" : 100,
    "lastUpdatedTime" : ISODate("2019-11-04T00:00:00.000Z"),
    "timetaken" : 3.0
}

/* 6 */
{
    "_id" : "CO",
    "value" : 100,
    "lastUpdatedTime" : ISODate("2019-11-04T00:00:00.000Z"),
    "timetaken" : 3.0
}

/* 7 */
{
    "_id" : "DD",
    "value" : 100,
    "lastUpdatedTime" : ISODate("2019-11-04T00:00:00.000Z"),
    "timetaken" : 3.0
}

/* 8 */
{
    "_id" : "EX",
    "value" : 100,
    "lastUpdatedTime" : ISODate("2019-11-04T00:00:00.000Z"),
    "timetaken" : 3.0
}

/* 9 */
{
    "_id" : "GS_SEG",
    "value" : 124755350,
    "lastUpdatedTime" : ISODate("2019-11-04T00:00:00.000Z"),
    "timetaken" : 3.0
}

/* 10 */
{
    "_id" : "GenFile",
    "value" : 200152,
    "lastUpdatedTime" : ISODate("2019-11-04T00:00:00.000Z"),
    "timetaken" : 3.0
}

【问题讨论】:

    标签: python mongodb mongodb-query pymongo


    【解决方案1】:

    您可以使用以下聚合为您完成工作。但是,它会将值字段 100,104 作为字符串而不是数字(我必须使用 toString 运算符,否则会出错)。

    db.collection.aggregate([
      {
        $group: {
          _id: "$value",
          root: {
            $push: "$$ROOT"
          }
        }
      },
      {
        $project: {
          k: {
            $toString: "$_id"
          },
          v: "$root",
          _id: 0
        }
      },
      {
        $group: {
          _id: null,
          x: {
            $push: "$$ROOT"
          }
        }
      },
      {
        $project: {
          _id: 0,
          x: {
            $arrayToObject: "$x"
          }
        }
      },
      {
        $replaceRoot: {
          newRoot: "$x"
        }
      }
    ])
    

    以下将是输出:

    [
      {
        "1.24755e+08": [
          {
            "_id": "GS_SEG",
            "lastUpdatedTime": ISODate("2019-11-04T00:00:00Z"),
            "timetaken": 3,
            "value": 1.2475535e+08
          }
        ],
        "100": [
          {
            "_id": "C1",
            "lastUpdatedTime": ISODate("2019-11-04T00:00:00Z"),
            "timetaken": 3,
            "value": 100
          },
          {
            "_id": "C2",
            "lastUpdatedTime": ISODate("2019-11-04T00:00:00Z"),
            "timetaken": 3,
            "value": 100
          },
          {
            "_id": "C3",
            "lastUpdatedTime": ISODate("2019-11-04T00:00:00Z"),
            "timetaken": 3,
            "value": 100
          },
          {
            "_id": "C4",
            "lastUpdatedTime": ISODate("2019-11-04T00:00:00Z"),
            "timetaken": 3,
            "value": 100
          },
          {
            "_id": "CO",
            "lastUpdatedTime": ISODate("2019-11-04T00:00:00Z"),
            "timetaken": 3,
            "value": 100
          },
          {
            "_id": "DD",
            "lastUpdatedTime": ISODate("2019-11-04T00:00:00Z"),
            "timetaken": 3,
            "value": 100
          },
          {
            "_id": "EX",
            "lastUpdatedTime": ISODate("2019-11-04T00:00:00Z"),
            "timetaken": 3,
            "value": 100
          }
        ],
        "104": [
          {
            "_id": "AU",
            "lastUpdatedTime": ISODate("2019-11-04T00:00:00Z"),
            "timetaken": 3,
            "value": 104
          }
        ],
        "200152": [
          {
            "_id": "GenFile",
            "lastUpdatedTime": ISODate("2019-11-04T00:00:00Z"),
            "timetaken": 3,
            "value": 200152
          }
        ]
      }
    ]
    

    【讨论】:

      【解决方案2】:

      您正在朝着正确的方向搜索,您将希望阻止您的代码将大部分时间花在网络请求上。 pymongo $in 运算符选择字段值等于指定数组中任何值的文档。

      在你的情况下,它看起来像这样:

      # Set or build a list of the values
      list_with_values =  [100, 104, 200152]
      
      # Make one call to the DB, asking for all of the matching records.
      result = db.getCollection('test').find({"value" : {"$in": list_with_values})
      

      关于$in 操作符如何工作的进一步参考:http://docs.mongodb.org/manual/reference/operator/query/in/

      【讨论】:

      • 这会给我整个文档然后我必须再次执行 python 查询以根据它们的值进行分离。由于此查询后返回的文档数量非常庞大,因此在 python 中执行 groupby "value" 也将非常耗时。
      • 我理解你的问题,当然提取数据和转换数据是有区别的。你可以看看这个答案:stackoverflow.com/a/38145104/9247792
      猜你喜欢
      • 1970-01-01
      • 2020-11-17
      • 2021-04-16
      • 2018-08-20
      • 2022-01-23
      • 1970-01-01
      • 2017-05-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多