MongoDB 中,聚合(Aggregation)是一种用于处理和分析数据的强大工具。聚合框架提供了一组操作符,可以对集合中的文档进行分组、筛选、排序、转换等操作,以生成新的结果集。聚合操作可以用于复杂的数据处理和分析任务,例如统计、分组计算、数据透视等。
聚合框架的核心是管道(Pipeline),它由一系列操作符组成,每个操作符都会对输入文档进行处理,并将结果传递给下一个操作符。聚合操作符可以按照顺序组合,以实现复杂的数据处理逻辑。
以下是一些常用的聚合操作符:
$match:用于筛选文档,类似于查询中的 find() 方法。
$group:用于分组文档,并对每个组进行聚合计算,如求和、平均值等。
$project:用于投影文档,即选择需要的字段,并可以进行计算和重命名等操作。
$sort:用于对文档进行排序。
$limit:用于限制输出文档的数量。
$skip:用于跳过指定数量的文档。
$unwind:用于展开数组字段,将数组中的每个元素作为独立的文档。
以下是一个使用聚合框架的示例,假设有一个名为 orders 的集合,包含了订单信息:
db.orders.aggregate([ { $match: { status: "completed" } }, // 筛选状态为 "completed" 的订单 { $group: { _id: "$customer", total: { $sum: "$amount" } } }, // 按客户 customer 分组,并计算订单总金额 { $sort: { total: -1 } }, // 按总金额降序排序 { $limit: 10 } // 只返回前 10 个结果 ]);
上面的聚合操作首先筛选出状态为 “completed” 的订单,然后按客户分组,并计算每个客户的订单总金额,然后按总金额降序排序,并只返回前 10 个结果。
注意:聚合操作是在数据库服务器上执行的,可以利用数据库的计算能力和索引来提高性能。聚合操作还可以与其他查询操作(如查询条件、索引等)组合使用,以实现更复杂的数据处理需求。
MongoDB 中聚合的方法使用 aggregate()。aggregate() 方法的基本语法格式如下所示:
db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)
其中,COLLECTION_NAME 为集合名称,AGGREGATE_OPERATION 为聚合操作对。
该示例将计算 col 集合中各种 sex 的 age 平均值。
(1)col 集合中的数据如下:
> db.col.find() { "_id" : ObjectId("64e71af810366fa87109a12f"), "name" : "张三", "age" : 18, "email" : "zhangsan@outlook.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a130"), "name" : "李四", "age" : 22, "email" : "lisi@qq.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a131"), "name" : "王五", "age" : 26, "email" : "wangwu@sina.com.cn", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a132"), "name" : "赵六", "age" : 27, "email" : "zhaoliu@gmail.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a133"), "name" : "顾七", "age" : 30, "email" : "guqi@qq.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a134"), "name" : "何八", "age" : 42, "email" : "heba@outlook.com", "sex" : "male" }
(2)计算各个 sex 下 age 的平均值:
> db.col.aggregate({ $group:{_id:"$sex", avg_age:{$avg:"$age"}} }) { "_id" : "male", "avg_age" : 29 } { "_id" : "female", "avg_age" : 24.5 }
以上示例类似的 sql 语句:
select sex, avg(age) from col group by sex;
在上面的例子中,我们通过字段 sex 字段对数据进行分组,并计算每个分组中 age 字段的平均值。
管道在 Unix 和 Linux 中一般用于将当前命令的输出结果作为下一个命令的参数。例如:
# 在文件中找出重复的行 $ sort testfile1 | uniq -d Hello 95 Linux 85 test 30
上面示例中,符号 | 就是管道符号。
在 MongoDB 中,MongoDB 的聚合管道将 MongoDB 文档在一个管道处理完毕后将结果传递给下一个管道处理,管道操作是可以重复的。
注意:聚合表达式处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档。
$project 操作符用于将聚合管道中的文档转换为指定的字段集合。它可以用于选择要返回的字段,计算新的字段值,重命名字段等操作。
$project 操作符接受一个包含字段映射的对象作为参数,其中键表示要包含或排除的字段,值表示是否包含或排除该字段。可以使用1表示包含该字段,0表示排除该字段。例如:
# col 集合所有数据 > db.col.find() { "_id" : ObjectId("64e71af810366fa87109a12f"), "name" : "张三", "age" : 18, "email" : "zhangsan@outlook.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a130"), "name" : "李四", "age" : 22, "email" : "lisi@qq.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a131"), "name" : "王五", "age" : 26, "email" : "wangwu@sina.com.cn", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a132"), "name" : "赵六", "age" : 27, "email" : "zhaoliu@gmail.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a133"), "name" : "顾七", "age" : 30, "email" : "guqi@qq.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a134"), "name" : "何八", "age" : 42, "email" : "heba@outlook.com", "sex" : "male" } # 通过投影,仅输出 name 和 age 字段,默认情况下 _id 字段是被包含的 > db.col.aggregate({ $project:{ name:1, age:1 } }) { "_id" : ObjectId("64e71af810366fa87109a12f"), "name" : "张三", "age" : 18 } { "_id" : ObjectId("64e71af810366fa87109a130"), "name" : "李四", "age" : 22 } { "_id" : ObjectId("64e71af810366fa87109a131"), "name" : "王五", "age" : 26 } { "_id" : ObjectId("64e71af810366fa87109a132"), "name" : "赵六", "age" : 27 } { "_id" : ObjectId("64e71af810366fa87109a133"), "name" : "顾七", "age" : 30 } { "_id" : ObjectId("64e71af810366fa87109a134"), "name" : "何八", "age" : 42 } # 通过投影,禁止输出 _id 字段,允许输出 name 和 age 字段 > db.col.aggregate({ $project:{ _id:0, name:1, age:1 } }) { "name" : "张三", "age" : 18 } { "name" : "李四", "age" : 22 } { "name" : "王五", "age" : 26 } { "name" : "赵六", "age" : 27 } { "name" : "顾七", "age" : 30 } { "name" : "何八", "age" : 42 }
$project 操作符还支持一些表达式和操作符,可以用于计算新的字段值。常用的表达式和操作符包括算术操作符(如 $add、$subtract、$multiply、$divide)、逻辑操作符(如 $and、$or、$not)、条件操作符(如 $ifNull、$cond)、字符串操作符(如 $concat、$substr)、日期操作符(如 $year、$month、$dayOfMonth)等。例如:
# col 集合所有数据 > db.col.find() { "_id" : ObjectId("64e71af810366fa87109a12f"), "name" : "张三", "age" : 27, "email" : "zhangsan@outlook.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a130"), "name" : "李四", "age" : 22, "email" : "lisi@qq.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a131"), "name" : "王五", "age" : 27, "email" : "wangwu@sina.com.cn", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a132"), "name" : "赵六", "age" : 22, "email" : "zhaoliu@gmail.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a133"), "name" : "顾七", "age" : 30, "email" : "guqi@qq.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a134"), "name" : "何八", "age" : 42, "email" : "heba@outlook.com", "sex" : "male" } # 使用 $multiply 操作符对 age 字段的值乘以 10 > db.col.aggregate({ $project:{_id:0, name:1, age:{$multiply:["$age",10]}} }) { "name" : "张三", "age" : 270 } { "name" : "李四", "age" : 220 } { "name" : "王五", "age" : 270 } { "name" : "赵六", "age" : 220 } { "name" : "顾七", "age" : 300 } { "name" : "何八", "age" : 420 }
$match 操作符用于筛选文档,类似于查询中的find()方法。它可以根据指定的条件选择符合条件的文档,并将它们作为聚合管道的输入。
$match 操作符接受一个查询条件作为参数,可以使用各种查询运算符和表达式来构建条件。常用的查询运算符包括$eq(等于)、$ne(不等于)、$gt(大于)、$lt(小于)、$gte(大于等于)、$lte(小于等于)、$in(在给定数组中)、$nin(不在给定数组中)等。例如:
# col 集合所有数据 > db.col.find() { "_id" : ObjectId("64e71af810366fa87109a12f"), "name" : "张三", "age" : 18, "email" : "zhangsan@outlook.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a130"), "name" : "李四", "age" : 22, "email" : "lisi@qq.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a131"), "name" : "王五", "age" : 26, "email" : "wangwu@sina.com.cn", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a132"), "name" : "赵六", "age" : 27, "email" : "zhaoliu@gmail.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a133"), "name" : "顾七", "age" : 30, "email" : "guqi@qq.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a134"), "name" : "何八", "age" : 42, "email" : "heba@outlook.com", "sex" : "male" } # 通过 $match 获取 age 大于 20 的文档,然后根据 sex 进行分组,计算每个分组 age 的平均值 > db.col.aggregate([ {$match:{age:{$gt:20}}}, {$group:{_id:"$sex", avg_age:{$avg:"$age"}}} ]) { "_id" : "female", "avg_age" : 24.5 } { "_id" : "male", "avg_age" : 32.666666666666664 }
注意:$match 操作符可以利用集合上的索引来提高查询性能。因此,在使用 $match 操作符时,应该根据查询条件创建适当的索引,以获得更好的性能。
$skip 操作符用于在聚合管道中跳过指定数量的文档,并返回剩余的文档。它可以用于实现分页功能,或者在聚合操作中跳过不需要的文档。
$skip 操作符接受一个整数作为参数,表示要跳过的文档数量。该参数必须是一个非负整数。例如:
# col 集合所有数据 > db.col.find() { "_id" : ObjectId("64e71af810366fa87109a12f"), "name" : "张三", "age" : 18, "email" : "zhangsan@outlook.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a130"), "name" : "李四", "age" : 22, "email" : "lisi@qq.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a131"), "name" : "王五", "age" : 26, "email" : "wangwu@sina.com.cn", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a132"), "name" : "赵六", "age" : 27, "email" : "zhaoliu@gmail.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a133"), "name" : "顾七", "age" : 30, "email" : "guqi@qq.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a134"), "name" : "何八", "age" : 42, "email" : "heba@outlook.com", "sex" : "male" } # 使用 $skip 操作符跳过前 4 个文档 > db.col.aggregate({ $skip:4 }) { "_id" : ObjectId("64e71af810366fa87109a133"), "name" : "顾七", "age" : 30, "email" : "guqi@qq.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a134"), "name" : "何八", "age" : 42, "email" : "heba@outlook.com", "sex" : "male" }
注意:$skip 操作符应该尽量在聚合管道的早期使用,以避免在后续的操作中处理不必要的文档。如果在聚合管道的后期使用 $skip 操作符,将会对性能产生负面影响,因为在跳过文档之前,MongoDB 仍然需要执行前面的聚合操作。
另外,如果要实现分页功能,可以将 $skip 操作符与 $limit 操作符结合使用。$limit 操作符用于限制返回的文档数量,可以用于分页查询。例如:
# col 集合所有数据 > db.col.find() { "_id" : ObjectId("64e71af810366fa87109a12f"), "name" : "张三", "age" : 27, "email" : "zhangsan@outlook.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a130"), "name" : "李四", "age" : 22, "email" : "lisi@qq.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a131"), "name" : "王五", "age" : 27, "email" : "wangwu@sina.com.cn", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a132"), "name" : "赵六", "age" : 22, "email" : "zhaoliu@gmail.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a133"), "name" : "顾七", "age" : 30, "email" : "guqi@qq.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a134"), "name" : "何八", "age" : 42, "email" : "heba@outlook.com", "sex" : "male" } # 跳过 col 集合前 3 个文档,然后仅仅获取 2 个文档 > db.col.aggregate([{ $skip:3 }, { $limit:2 }]) { "_id" : ObjectId("64e71af810366fa87109a132"), "name" : "赵六", "age" : 22, "email" : "zhaoliu@gmail.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a133"), "name" : "顾七", "age" : 30, "email" : "guqi@qq.com", "sex" : "male" }
计算总和。例如:
# col 集合所有数据 > db.col.find() { "_id" : ObjectId("64e71af810366fa87109a12f"), "name" : "张三", "age" : 18, "email" : "zhangsan@outlook.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a130"), "name" : "李四", "age" : 22, "email" : "lisi@qq.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a131"), "name" : "王五", "age" : 26, "email" : "wangwu@sina.com.cn", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a132"), "name" : "赵六", "age" : 27, "email" : "zhaoliu@gmail.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a133"), "name" : "顾七", "age" : 30, "email" : "guqi@qq.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a134"), "name" : "何八", "age" : 42, "email" : "heba@outlook.com", "sex" : "male" } # 使用 sex 进行分组,计算每个分组 age 的总和 > db.col.aggregate({ $group:{_id:"$sex", age_sum:{$sum:"$age"}} }) { "_id" : "male", "age_sum" : 116 } { "_id" : "female", "age_sum" : 49 }
计算平均值。例如:
# col 集合所有数据 > db.col.find() { "_id" : ObjectId("64e71af810366fa87109a12f"), "name" : "张三", "age" : 18, "email" : "zhangsan@outlook.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a130"), "name" : "李四", "age" : 22, "email" : "lisi@qq.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a131"), "name" : "王五", "age" : 26, "email" : "wangwu@sina.com.cn", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a132"), "name" : "赵六", "age" : 27, "email" : "zhaoliu@gmail.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a133"), "name" : "顾七", "age" : 30, "email" : "guqi@qq.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a134"), "name" : "何八", "age" : 42, "email" : "heba@outlook.com", "sex" : "male" } # 使用 sex 进行分组,计算每个分组 age 的平均值 > db.col.aggregate({ $group:{_id:"$sex", age_avg:{$avg:"$age"}} }) { "_id" : "female", "age_avg" : 24.5 } { "_id" : "male", "age_avg" : 29 }
获取集合中所有文档对应值得最小值。例如:
# col 集合所有数据 > db.col.find() { "_id" : ObjectId("64e71af810366fa87109a12f"), "name" : "张三", "age" : 18, "email" : "zhangsan@outlook.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a130"), "name" : "李四", "age" : 22, "email" : "lisi@qq.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a131"), "name" : "王五", "age" : 26, "email" : "wangwu@sina.com.cn", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a132"), "name" : "赵六", "age" : 27, "email" : "zhaoliu@gmail.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a133"), "name" : "顾七", "age" : 30, "email" : "guqi@qq.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a134"), "name" : "何八", "age" : 42, "email" : "heba@outlook.com", "sex" : "male" } # 使用 sex 进行分组,获取每个分组最小的 age 值 > db.col.aggregate({ $group:{_id:"$sex", age_min:{$min:"$age"}} }) { "_id" : "male", "age_min" : 18 } { "_id" : "female", "age_min" : 22 }
获取集合中所有文档对应值得最大值。例如:
# col 集合所有数据 > db.col.find() { "_id" : ObjectId("64e71af810366fa87109a12f"), "name" : "张三", "age" : 18, "email" : "zhangsan@outlook.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a130"), "name" : "李四", "age" : 22, "email" : "lisi@qq.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a131"), "name" : "王五", "age" : 26, "email" : "wangwu@sina.com.cn", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a132"), "name" : "赵六", "age" : 27, "email" : "zhaoliu@gmail.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a133"), "name" : "顾七", "age" : 30, "email" : "guqi@qq.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a134"), "name" : "何八", "age" : 42, "email" : "heba@outlook.com", "sex" : "male" } # 使用 sex 进行分组,获取每个分组最大的 age 值 > db.col.aggregate({ $group:{_id:"$sex", age_max:{$max:"$age"}} }) { "_id" : "female", "age_max" : 27 } { "_id" : "male", "age_max" : 42 }
将值加入一个数组中,不会判断是否有重复的值。例如:
# col 集合所有数据 > db.col.find() { "_id" : ObjectId("64e71af810366fa87109a12f"), "name" : "张三", "age" : 18, "email" : "zhangsan@outlook.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a130"), "name" : "李四", "age" : 22, "email" : "lisi@qq.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a131"), "name" : "王五", "age" : 26, "email" : "wangwu@sina.com.cn", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a132"), "name" : "赵六", "age" : 27, "email" : "zhaoliu@gmail.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a133"), "name" : "顾七", "age" : 30, "email" : "guqi@qq.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a134"), "name" : "何八", "age" : 42, "email" : "heba@outlook.com", "sex" : "male" } # 使用 sex 进行分组,将每个分组的 age 组成一个数组 > db.col.aggregate({ $group:{_id:"$sex", ages:{$push:"$age"}} }) { "_id" : "female", "ages" : [ 22, 22 ] } { "_id" : "male", "ages" : [ 27, 27, 30, 42 ] }
将值加入一个数组中,会判断是否有重复的值,若相同的值在数组中已经存在了,则不加入。例如:
# col 集合所有数据 > db.col.find() { "_id" : ObjectId("64e71af810366fa87109a12f"), "name" : "张三", "age" : 27, "email" : "zhangsan@outlook.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a130"), "name" : "李四", "age" : 22, "email" : "lisi@qq.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a131"), "name" : "王五", "age" : 27, "email" : "wangwu@sina.com.cn", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a132"), "name" : "赵六", "age" : 22, "email" : "zhaoliu@gmail.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a133"), "name" : "顾七", "age" : 30, "email" : "guqi@qq.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a134"), "name" : "何八", "age" : 42, "email" : "heba@outlook.com", "sex" : "male" } # 使用 sex 进行分组,将每个分组的 age 组成一个数组 > db.col.aggregate({ $group:{_id:"$sex", ages:{$addToSet:"$age"}} }) { "_id" : "male", "ages" : [ 27, 42, 30 ] } { "_id" : "female", "ages" : [ 22 ] }
根据资源文档的排序获取第一个文档数据。例如:
# col 集合所有数据 > db.col.find() { "_id" : ObjectId("64e71af810366fa87109a12f"), "name" : "张三", "age" : 18, "email" : "zhangsan@outlook.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a130"), "name" : "李四", "age" : 22, "email" : "lisi@qq.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a131"), "name" : "王五", "age" : 26, "email" : "wangwu@sina.com.cn", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a132"), "name" : "赵六", "age" : 27, "email" : "zhaoliu@gmail.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a133"), "name" : "顾七", "age" : 30, "email" : "guqi@qq.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a134"), "name" : "何八", "age" : 42, "email" : "heba@outlook.com", "sex" : "male" } # 使用 sex 进行分组,获取每个分组文档中第一个文档的 age 值 > db.col.aggregate({ $group:{_id:"$sex", age:{$first:"$age"}} }) { "_id" : "female", "age" : 22 } { "_id" : "male", "age" : 18 }
根据资源文档的排序获取最后一个文档数据。例如:
# col 集合所有数据 > db.col.find() { "_id" : ObjectId("64e71af810366fa87109a12f"), "name" : "张三", "age" : 18, "email" : "zhangsan@outlook.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a130"), "name" : "李四", "age" : 22, "email" : "lisi@qq.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a131"), "name" : "王五", "age" : 26, "email" : "wangwu@sina.com.cn", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a132"), "name" : "赵六", "age" : 27, "email" : "zhaoliu@gmail.com", "sex" : "female" } { "_id" : ObjectId("64e71af810366fa87109a133"), "name" : "顾七", "age" : 30, "email" : "guqi@qq.com", "sex" : "male" } { "_id" : ObjectId("64e71af810366fa87109a134"), "name" : "何八", "age" : 42, "email" : "heba@outlook.com", "sex" : "male" } # 使用 sex 进行分组,获取每个分组文档中最后一个文档的 age 值 > db.col.aggregate({ $group:{_id:"$sex", age:{$last:"$age"}} }) { "_id" : "female", "age" : 27 } { "_id" : "male", "age" : 42 }