本文研究查询过程中,定义数组返回结果的另外一个操作符$elemMatch。
定义
投射中elemMatch与操作符号一样,都是返回数组中第一个符合查询条件的数据。
但两个操作命令也有差异。使用符号时,用户只能通过查询条件来过滤数组元素。而使用elemMatch时,用户可以显示的定义更多的数组过滤条件。同时$elemMatch也支持文档数组中多个字段的查询条件定义。
字段顺序
在投射中,无论用户定义返回多少个字段,使用elemMatch和操作符号时, 4.4以后版本的mongodb都会将符合查询条件的数组结果,置于所有字段的后面。
向player集合插入一条数据
db.players.insertOne({
name: "player1",
games: [
{ game: "abc", score: 8},
{ game: "xyz", score: 5}
],
joined: new Date("2020-01-01"),
lastLogin: new Date("2020-05-01")
})
使用$elemMatch构建查询语句,查找出score大于5的数据。其中指定返回字段games, joined, lastLogin
db.players.find(
{},
{
games: {$elemMatch: {"score": {$gt: 5}}},
joined: 1,
lastLogin: 1
})
查询结果中, games字段排列到了joined和lastLogin后。而在4.2及以前的mongodb版本中,games字段会按照用户查询投射中定义的字段顺序返回。
{
"_id" : ObjectId("65b594f1374038b32213a3e5"),
"joined" : ISODate("2020-01-01T08:00:00.000+08:00"),
"lastLogin" : ISODate("2020-05-01T08:00:00.000+08:00"),
"games" : [
{
"game" : "abc",
"score" : 8
}
]
}
使用限制
- mongodb 视图中,不支持使用$elemMatch查询。
- 在elemMatch中不能使用text查询表达式。
应用举例
构建测试集合
向schools集合中,插入带有数组students的4条数据
db.schools.insertMany([
{
_id: 1,
zipcode: "63109",
students: [
{ name: "john", school: 102, age: 10 },
{ name: "jess", school: 102, age: 11 },
{ name: "jeff", school: 108, age: 15 }
]
},
{
_id: 2,
zipcode: "63110",
students: [
{ name: "ajax", school: 100, age: 7 },
{ name: "achilles", school: 100, age: 8 },
]
},
{
_id: 3,
zipcode: "63109",
students: [
{ name: "ajax", school: 100, age: 7 },
{ name: "achilles", school: 100, age: 8 },
]
},
{
_id: 4,
zipcode: "63109",
students: [
{ name: "barney", school: 102, age: 7 },
{ name: "ruth", school: 102, age: 16 },
]
}
])
单字段查询
查询出zipcode是63109的数据,在返回结果中,显示第一个school是102的学生数据。
db.schools.find(
{zipcode: "63109"},
{students: {$elemMatch: { school: 102}}}
)
返回结果
/* 1 */
{
"_id" : 1,
"students" : [
{
"name" : "john",
"school" : 102,
"age" : 10
}
]
},
/* 2 */
{
"_id" : 3
},
/* 3 */
{
"_id" : 4,
"students" : [
{
"name" : "barney",
"school" : 102,
"age" : 7
}
]
}
多字段查询
构建查询语句,返回zipcode是63109的数据。要求结果中返回第一个字段school是102,并且age大于10的数据。
db.schools.find(
{zipcode: "63109"},
{students: {$elemMatch: { school: 102, age: {$gt: 10}}}}
)
返回结果
/* 1 */
{
"_id" : 1,
"students" : [
{
"name" : "jess",
"school" : 102,
"age" : 11
}
]
},
/* 2 */
{
"_id" : 3
},
/* 3 */
{
"_id" : 4,
"students" : [
{
"name" : "ruth",
"school" : 102,
"age" : 16
}
]
}