如何像HashMap(键值对)一样从mongoDB获取数据

问题描述 投票:0回答:2

这是我的mongodb中的记录

{
    "_id": "5a65a047992e3c2572f74102",
    "_class": "com.vuelogix.location.model.LocationModel",
    "type": "Feature",
    "properties": {
        "address": "Purna to Loha Rd, Maharashtra 431511, India",
        "device_id": 23613,
        "last_updated": "2018-01-22T08:26:47.237Z"
    },
    "geometry": {
        "_class": "com.vuelogix.location.model.geojson.geometry.Point",
        "coordinates": [77.065659, 19.145168],
        "type": "Point"
    }
},

{
    "_id": "5a65ae1e992e3c2572f74114",
    "_class": "com.vuelogix.location.model.LocationModel",
    "type": "Feature",
    "properties": {
        "address": "Taranagar - Churu Rd, Chalkoi Baneerotan, Rajasthan 331001, India",
        "device_id": 23658,
        "last_updated": "2018-01-22T09:25:50.893Z"
    },
    "geometry": {
        "_class": "com.vuelogix.location.model.geojson.geometry.Point",
        "coordinates": [74.956284, 28.497661],
        "type": "Point"
    }
}

我想将其作为键值对获取: 键应为“properties.device_id”并值整个记录

像这样

[23613] => {
    "_id": "5a65a047992e3c2572f74102",
    "_class": "com.vuelogix.location.model.LocationModel",
    "type": "Feature",
    "properties": {
        "address": "Purna to Loha Rd, Maharashtra 431511, India",
        "device_id": 23613,
        "last_updated": "2018-01-22T08:26:47.237Z"
    },
    "geometry": {
        "_class": "com.vuelogix.location.model.geojson.geometry.Point",
        "coordinates": [77.065659, 19.145168],
        "type": "Point"
    }
}

[23658] => {
    "_id": "5a65ae1e992e3c2572f74114",
    "_class": "com.vuelogix.location.model.LocationModel",
    "type": "Feature",
    "properties": {
        "address": "Taranagar - Churu Rd, Chalkoi Baneerotan, Rajasthan 331001, India",
        "device_id": 23658,
        "last_updated": "2018-01-22T09:25:50.893Z"
    },
    "geometry": {
        "_class": "com.vuelogix.location.model.geojson.geometry.Point",
        "coordinates": [74.956284, 28.497661],
        "type": "Point"
    }
}

有没有办法在不迭代记录的情况下获得这样的结果?

mongodb hashmap mongodb-query aggregation-framework
2个回答
1
投票

使用

$addFields
管道阶段创建一个新字段,例如
root
,它是包含两个字段
k
v
的文档数组,其中:

The k field contains the field name.
The v field contains the value of the field.

在您的情况下,

k
应该是
device_id
字段。由于这是双精度类型,因此您需要将其转换为字符串以供稍后使用。所以你的初始管道如下所示:

db.collection.aggregate([
    {
        "$addFields": {
            "root": [
                {
                    "k": { "$substr": [ "$properties.device_id", 0, -1 ] },
                    "v": "$$ROOT"
                }
            ]                
        }
    }
])

将返回以下文件

/* 1 */
{
    "_id" : "5a65a047992e3c2572f74102",
    "_class" : "com.vuelogix.location.model.LocationModel",
    "type" : "Feature",
    "properties" : {
        "address" : "Purna to Loha Rd, Maharashtra 431511, India",
        "device_id" : 23613.0,
        "last_updated" : "2018-01-22T08:26:47.237Z"
    },
    "geometry" : {
        "_class" : "com.vuelogix.location.model.geojson.geometry.Point",
        "coordinates" : [ 
            77.065659, 
            19.145168
        ],
        "type" : "Point"
    },
    "root" : [ 
        {
            "k" : "23613",
            "v" : {
                "_id" : "5a65a047992e3c2572f74102",
                "_class" : "com.vuelogix.location.model.LocationModel",
                "type" : "Feature",
                "properties" : {
                    "address" : "Purna to Loha Rd, Maharashtra 431511, India",
                    "device_id" : 23613.0,
                    "last_updated" : "2018-01-22T08:26:47.237Z"
                },
                "geometry" : {
                    "_class" : "com.vuelogix.location.model.geojson.geometry.Point",
                    "coordinates" : [ 
                        77.065659, 
                        19.145168
                    ],
                    "type" : "Point"
                }
            }
        }
    ]
}

/* 2 */
{
    "_id" : "5a65ae1e992e3c2572f74114",
    "_class" : "com.vuelogix.location.model.LocationModel",
    "type" : "Feature",
    "properties" : {
        "address" : "Taranagar - Churu Rd, Chalkoi Baneerotan, Rajasthan 331001, India",
        "device_id" : 23658.0,
        "last_updated" : "2018-01-22T09:25:50.893Z"
    },
    "geometry" : {
        "_class" : "com.vuelogix.location.model.geojson.geometry.Point",
        "coordinates" : [ 
            74.956284, 
            28.497661
        ],
        "type" : "Point"
    },
    "root" : [ 
        {
            "k" : "23658",
            "v" : {
                "_id" : "5a65ae1e992e3c2572f74114",
                "_class" : "com.vuelogix.location.model.LocationModel",
                "type" : "Feature",
                "properties" : {
                    "address" : "Taranagar - Churu Rd, Chalkoi Baneerotan, Rajasthan 331001, India",
                    "device_id" : 23658.0,
                    "last_updated" : "2018-01-22T09:25:50.893Z"
                },
                "geometry" : {
                    "_class" : "com.vuelogix.location.model.geojson.geometry.Point",
                    "coordinates" : [ 
                        74.956284, 
                        28.497661
                    ],
                    "type" : "Point"
                }
            }
        }
    ]
}

从这里开始,您需要利用

$arrayToObject
运算符,以便将新添加的根转换为以
device_id
作为键的对象:

db.collection.aggregate([
    {
        "$addFields": {
            "root": [
                {
                    "k": { "$substr": [ "$properties.device_id", 0, -1 ] },
                    "v": "$$ROOT"
                }
            ]                
        }
    },
    {
        "$addFields": {
            "root": {
                "$arrayToObject": "$root"
            }             
        }
    }
])

输出:

/* 1 */
{
    "_id" : "5a65a047992e3c2572f74102",
    "_class" : "com.vuelogix.location.model.LocationModel",
    "type" : "Feature",
    "properties" : {
        "address" : "Purna to Loha Rd, Maharashtra 431511, India",
        "device_id" : 23613.0,
        "last_updated" : "2018-01-22T08:26:47.237Z"
    },
    "geometry" : {
        "_class" : "com.vuelogix.location.model.geojson.geometry.Point",
        "coordinates" : [ 
            77.065659, 
            19.145168
        ],
        "type" : "Point"
    },
    "root" : {
        "23613" : {
            "_id" : "5a65a047992e3c2572f74102",
            "_class" : "com.vuelogix.location.model.LocationModel",
            "type" : "Feature",
            "properties" : {
                "address" : "Purna to Loha Rd, Maharashtra 431511, India",
                "device_id" : 23613.0,
                "last_updated" : "2018-01-22T08:26:47.237Z"
            },
            "geometry" : {
                "_class" : "com.vuelogix.location.model.geojson.geometry.Point",
                "coordinates" : [ 
                    77.065659, 
                    19.145168
                ],
                "type" : "Point"
            }
        }
    }
}

/* 2 */
{
    "_id" : "5a65ae1e992e3c2572f74114",
    "_class" : "com.vuelogix.location.model.LocationModel",
    "type" : "Feature",
    "properties" : {
        "address" : "Taranagar - Churu Rd, Chalkoi Baneerotan, Rajasthan 331001, India",
        "device_id" : 23658.0,
        "last_updated" : "2018-01-22T09:25:50.893Z"
    },
    "geometry" : {
        "_class" : "com.vuelogix.location.model.geojson.geometry.Point",
        "coordinates" : [ 
            74.956284, 
            28.497661
        ],
        "type" : "Point"
    },
    "root" : {
        "23658" : {
            "_id" : "5a65ae1e992e3c2572f74114",
            "_class" : "com.vuelogix.location.model.LocationModel",
            "type" : "Feature",
            "properties" : {
                "address" : "Taranagar - Churu Rd, Chalkoi Baneerotan, Rajasthan 331001, India",
                "device_id" : 23658.0,
                "last_updated" : "2018-01-22T09:25:50.893Z"
            },
            "geometry" : {
                "_class" : "com.vuelogix.location.model.geojson.geometry.Point",
                "coordinates" : [ 
                    74.956284, 
                    28.497661
                ],
                "type" : "Point"
            }
        }
    }
}

管道中的最后一步是使用

$replaceRoot
管道运算符来获取所需的输出:

db.collection.aggregate([
    {
        "$addFields": {
            "root": [
                {
                    "k": { "$substr": [ "$properties.device_id", 0, -1 ] },
                    "v": "$$ROOT"
                }
            ]                
        }
    },
    {
        "$addFields": {
            "root": {
                "$arrayToObject": "$root"
            }             
        }
    },
    { "$replaceRoot" : { "newRoot": "$root" } }    
])

输出

/* 1 */
{
    "23613" : {
        "_id" : "5a65a047992e3c2572f74102",
        "_class" : "com.vuelogix.location.model.LocationModel",
        "type" : "Feature",
        "properties" : {
            "address" : "Purna to Loha Rd, Maharashtra 431511, India",
            "device_id" : 23613.0,
            "last_updated" : "2018-01-22T08:26:47.237Z"
        },
        "geometry" : {
            "_class" : "com.vuelogix.location.model.geojson.geometry.Point",
            "coordinates" : [ 
                77.065659, 
                19.145168
            ],
            "type" : "Point"
        }
    }
}

/* 2 */
{
    "23658" : {
        "_id" : "5a65ae1e992e3c2572f74114",
        "_class" : "com.vuelogix.location.model.LocationModel",
        "type" : "Feature",
        "properties" : {
            "address" : "Taranagar - Churu Rd, Chalkoi Baneerotan, Rajasthan 331001, India",
            "device_id" : 23658.0,
            "last_updated" : "2018-01-22T09:25:50.893Z"
        },
        "geometry" : {
            "_class" : "com.vuelogix.location.model.geojson.geometry.Point",
            "coordinates" : [ 
                74.956284, 
                28.497661
            ],
            "type" : "Point"
        }
    }
}

0
投票

@chridam 的答案并不返回实际的键值 hashMap,而是返回一个对象数组,其值位于单个键后面。

[ {"23613":{...} }, {"23658":{...} }] 
vs. 
{"23613":{...}, "23658":{...} }

要获取实际的键值对 HashMap 结果,您可以使用以下聚合:

db.collection.aggregate([
  {
    $group: {
      _id: "",
      data: {
        $mergeObjects: {
          $arrayToObject: [
            [
              {
                k: {
                  $toString: "$properties.device_id"
                },
                v: "$$ROOT"
              }
            ]
          ]
        }
      }
    }
  },
  {
    $replaceRoot: {
      newRoot: "$data"
    }
  }
]);

这将返回:

[
  {
    "23613": {
      "_class": "com.vuelogix.location.model.LocationModel",
      "_id": "5a65a047992e3c2572f74102",
      "geometry": {
        "_class": "com.vuelogix.location.model.geojson.geometry.Point",
        "coordinates": [
          77.065659,
          19.145168
        ],
        "type": "Point"
      },
      "properties": {
        "address": "Purna to Loha Rd, Maharashtra 431511, India",
        "device_id": 23613,
        "last_updated": "2018-01-22T08:26:47.237Z"
      },
      "type": "Feature"
    },
    "23658": {
      "_class": "com.vuelogix.location.model.LocationModel",
      "_id": "5a65ae1e992e3c2572f74114",
      "geometry": {
        "_class": "com.vuelogix.location.model.geojson.geometry.Point",
        "coordinates": [
          74.956284,
          28.497661
        ],
        "type": "Point"
      },
      "properties": {
        "address": "Taranagar - Churu Rd, Chalkoi Baneerotan, Rajasthan 331001, India",
        "device_id": 23658,
        "last_updated": "2018-01-22T09:25:50.893Z"
      },
      "type": "Feature"
    }
  }
]

如您所见,结果仍然是一个数组,因为聚合函数的行为始终是返回一个数组。从积极的一面来看,这个数组将始终只包含 1 个文档/对象。这个对象就是你的键值对HashMap。因此,每当您在应用程序中使用结果时,您始终必须从结果数组中获取第一个文档:

result.get(0)
result[0]
或任何适合您的编程语言的内容。

聚合查询说明:

$group

  • 将所有文档分组到一个组中。使用
    _id: ""
    可确保所有文档都添加/合并到一个组中。
  • 聚合数据字段,创建单个合并对象。

$mergeObjects

  • 将多个对象合并为一个对象。在这里,它用于组合 $arrayToObject 生成的对象。

$arrayToObject

  • 将键值对数组转换为对象。
  • k(key):“$properties.device_id”的字符串化值,因为 key 必须是字符串。
  • v(值):原始集合中的完整文档(“$$ROOT”)。

$replaceRoot

  • 用数据字段的值替换结果的根文档。
  • 数据字段(在上一阶段创建)是所有文档的合并对象,以
    device_id
    值作为键。
© www.soinside.com 2019 - 2024. All rights reserved.