$first(数组操作符)
定义
语法
$first
通过以下语法实现:
{ $first: <expression> }
<expression>
可以是任何有效的表达式,只要它解析为数组即可,可以为 null 或缺失。 有关表达式的更多信息,请参阅表达式。
$first
操作符是以下$arrayElemAt
表达式的别名:
{ $arrayElemAt: [ <array expression>, 0 ] }
行为
有效操作数
$first
的有效操作数必须解析为数组、为 null 或缺失
例如,使用以下文档创建测试collectionexample1
:
db.example1.insertMany([ { "_id" : 1, "x" : [ 1, 2, 3 ] }, // Non-empty array { "_id" : 2, "x" : [ [ ] ] }, // Non-empty array { "_id" : 3, "x" : [ null ] }, // Non-empty array { "_id" : 4, "x" : [ ] }, // Empty array { "_id" : 5, "x" : null }, // Is null { "_id" : 6 } // Is Missing ])
然后,以下代码添加一个新字段firstElem
,其值通过将$first
操作符应用于x
字段而派生:
db.example1.aggregate([ { $addFields: { firstElem: { $first: "$x" } } } ])
操作符返回以下文档:
{ "_id" : 1, "x" : [ 1, 2, 3 ], "firstElem" : 1 } { "_id" : 2, "x" : [ [ ] ], "firstElem" : [ ] } { "_id" : 3, "x" : [ null ], "firstElem" : null } { "_id" : 4, "x" : [ ] } // No output { "_id" : 5, "x" : null, "firstElem" : null } { "_id" : 6, "firstElem" : null }
无效操作数
如果操作数未解析为数组、为 null 或缺失,则整个聚合操作都会出错。
例如,使用以下文档创建测试collectionexample2
:
db.example2.insertMany([ { "_id" : 1, "x" : [ 1, 2, 3 ] }, { "_id" : 2, "x" : 2 }, // x is not an array/null or missing ])
然后,以下聚合操作会因{ "_id" : 2, "x" : 2 }
文档而返回错误:
db.example2.aggregate( { $addFields: { firstElem: { $first: "$x" } } } )
也就是说,该操作返回以下内容:
2020-01-20T18:31:13.431-05:00 E QUERY [js] uncaught exception: Error: command failed: { "ok" : 0, "errmsg" : "$first's argument must be an array, but is double", "code" : 28689, "codeName" : "Location28689" } : aggregate failed :
例子
使用以下文档创建样本collectionrunninglog
:
db.runninglog.insertMany([ { "_id" : 1, "team" : "Anteater", log: [ { run: 1, distance: 8 }, { run2: 2, distance: 7.5 }, { run: 3, distance: 9.2 } ] }, { "_id" : 2, "team" : "Bears", log: [ { run: 1, distance: 18 }, { run2: 2, distance: 17 }, { run: 3, distance: 16 } ] }, { "_id" : 3, "team" : "Cobras", log: [ { run: 1, distance: 2 } ] } ])
以下聚合在log
数组上使用$first
和$last
操作符来检索第一次运行和最后一次运行的信息:
db.runninglog.aggregate([ { $addFields: { firstrun: { $first: "$log" }, lastrun: { $last: "$log" } } } ])
操作返回以下结果:
{ "_id" : 1, "team" : "Anteater", "log" : [ { "run" : 1, "distance" : 8 }, { "run2" : 2, "distance" : 7.5 }, { "run" : 3, "distance" : 9.2 } ], "firstrun" : { "run" : 1, "distance" : 8 }, "lastrun" : { "run" : 3, "distance" : 9.2 } } { "_id" : 2, "team" : "Bears", "log" : [ { "run" : 1, "distance" : 18 }, { "run2" : 2, "distance" : 17 }, { "run" : 3, "distance" : 16 } ], "firstrun" : { "run" : 1, "distance" : 18 }, "lastrun" : { "run" : 3, "distance" : 16 } } { "_id" : 3, "team" : "Cobras", "log" : [ { "run" : 1, "distance" : 2 } ], "firstrun" : { "run" : 1, "distance" : 2 }, "lastrun" : { "run" : 1, "distance" : 2 } }
为了计算第一个距离和最后一个距离之间的变化,以下操作使用$cond
和$size
操作符来计算差值(即 $subtract
),如果log
数组中有两个或多个元素,则这两个距离:
db.runninglog.aggregate([ { $addFields: { firstrun: { $first: "$log" }, lastrun: { $last: "$log" } } }, { $project: { team: 1, progress: { $cond: { if: { $gt: [ { $size:"$log" }, 1 ] } , then: { $subtract: [ "$lastrun.distance", "$firstrun.distance"] }, else: "Not enough data." } } }} ])
该操作将返回以下文档:
{ "_id" : 1, "team" : "Anteater", "progress" : 1.1999999999999993 } { "_id" : 2, "team" : "Bears", "progress" : -2 } { "_id" : 3, "team" : "Cobras", "progress" : "Not enough data." }
默认, mongosh
使用 64 位浮点double精度值来表示数字。 要提高精度,可以改用NumberDecimal 。