如何在没有KeyErrors的情况下使用Python和MongoDB跳过不存在的键

时间:2015-12-28 13:14:16

标签: python django mongodb dictionary

使用MongoDB存储来自嵌入式设备的少量事件详细信息和Django作为Web应用程序包装数据。 device_events集合具有以下类型的记录:

{"key1": value1,
 "key2": value2,
 "key3": value3, 
 "key4" : {
    "type" : "Point", 
    "coordinates" : [
        87.55092545050022, 
        25.037010399709558
    ]
}, 
 "key5": value5,
}

在同一个集合中,很少有记录可以是另一种类型:

  {"key9": value9,
     "keyx": valuex,
     "key3": value3, 
     "key4" : {
        "type" : "Point", 
        "coordinates" : [
            87.55092545050022, 
            25.037010399709558
        ]
    }, 
     "key5": value5,
    } 

当我查询集合中的所有记录时,我会获得所有dict的列表。我想使用map-lambda来获取所需的字段数据。

现在的问题是,一条记录存在的字段很少,很少有字段存在。我需要在报告中显示该字段而不管是否存在,如果密钥不存在,则可能需要null / zero。

我的地图功能是:

data ={
        "data" : map(
            lambda m: {
                "id": m["key1"], "longitude": m["key4"]["coordinates"][0], "latitude": m["key4"]["coordinates"][1],"active_status" : m["keyx"]
            },
            all_devices
        )
    }

引发了什么,KeyError:'id'。

我需要将它用于包含大量数据的报告,需要有最小开销的高效解决方案。 [我的意思是检查列表中的每个字典,因为在这种情况下,每个键都不是最佳解决方案。]

提前致谢!!

2 个答案:

答案 0 :(得分:1)

正如我在评论中所说,如果你必须检查词典中是否存在密钥,我就不会使用单行代码。

我相信最快的方法是使用try / except:

def my_func(some_dict):
    out_dict = {}
    try:
        id = some_dict['key1']
    except KeyError:
        id = None
    try:
        long = some_dict["key4"]["coordinates"][0]
    except KeyError:
        long = None
    try:
        lat = some_dict["key4"]["coordinates"][1]
    except KeyError:
        lat = None
    try:
        act = some_dict["keyx"]
    except KeyError:
        act = None
    return {"id": id, "longitude": long, "latitude": lat,"active_status" : act}

data ={"data" : map(my_func,all_devices)}

如果您仍然需要“单行”,那么您可以执行以下操作:

data ={
        "data" : map(
            lambda m: {
                "id": m["key1"] if "key1" in m else None,
                "longitude": m["key4"]["coordinates"][0]  if "key4" in m else None,
                "latitude": m["key4"]["coordinates"][1]  if "key4" in m else None,
                "active_status" : m["keyx"]  if "keyx" in m else None
            },
            all_devices
        )
    }

data ={
        "data" : map(
            lambda m: {
                "id": ((if "key1" in m) and m["key1"]) or None,
                "longitude": ((if "key4" in m) and m["key4"]["coordinates"][0]) or None,
                "latitude":((if "key4" in m) and  m["key4"]["coordinates"][1]) or None,
                "active_status" : ((if "keyx" in m) and m["keyx"]) or None
            },
            all_devices
        )
    }

答案 1 :(得分:0)

由于您希望简化映射,因此在应用地图之前,您必须确保数据已完成

如果您可以控制进入数据库的内容,请确保在那里添加必填字段。

否则,在从数据库中提取词典之后但在运行map之前,将缺少的键添加到词典中:

def checker(d):
    for k in ["key1", "key4", "keyx"]:
        if k not in d:
            d[k] = None  # or 0, or ''. Whatever works for you.

data = [checker(d) for d in data]