前面看到mongodb文档的字段的值可以嵌套一个文档,当然字段的值也可以嵌套一个数组。不过嵌套数组就比嵌套文档稍微复杂一些,因为数组既可以是基本数据类型的数组,也可以是文档类型的数组。为了逻辑的顺畅,先从嵌套基本数据类型的数组开始,然后过度到嵌套文档的数组。
#########################################################################
基本数据的数组:
1. 精确匹配 数组中值完全一样,值的顺序也一致
// 样例数据
{ "_id" : 1, "score" : [ -1, 3 ] }
{ "_id" : 2, "score" : [ 1, 5 ] }
{ "_id" : 3, "score" : [ 1, 5, 6 ] }
{ "_id" : 4, "score" : [ 5, 6 ] }
{ "_id" : 5, "score" : [ 5, 1 ] }
// 精确查询
db.students.find( { score: [1, 5] } )
// 匹配的只有一个
{ "_id" : 2, "score" : [ 1, 5 ] }
// 下面两个不会匹配 顺序不一样 个数不一样
{ "_id" : 5, "score" : [ 5, 1 ] }
{ "_id" : 3, "score" : [ 1, 5, 6 ] }
2. 匹配数组单个元素 也就是数据中有一个元素等于查询的这个元素 就返回。
// 样例数据
{ "_id" : 1, "score" : [ -1, 3 ] }
{ "_id" : 2, "score" : [ 1, 5 ] }
{ "_id" : 3, "score" : [ 1, 5, 6 ] }
{ "_id" : 4, "score" : [ 5, 6 ] }
{ "_id" : 5, "score" : [ 5, 1 ] }
// 匹配数组一个元素
db.students.find( { score: 5 } )
// 返回的文档是
{ "_id" : 2, "score" : [ 1, 5 ] }// 5
{ "_id" : 3, "score" : [ 1, 5, 6 ] }// 5
{ "_id" : 4, "score" : [ 5, 6 ] }// 5
{ "_id" : 5, "score" : [ 5, 1 ] }// 5
3. 匹配数组多个元素 也就是所有的查询条件都可以在数组中找到匹配的元素,可以是单个元素满足所有条件,也可以是多个元素-每个元素只满足一个条件。
// 样例数据
{ "_id" : 1, "score" : [ -1, 3 ] }
{ "_id" : 2, "score" : [ 1, 5 ] }
{ "_id" : 3, "score" : [ 1, 5, 6 ] }
{ "_id" : 4, "score" : [ 5, 6 ] }
{ "_id" : 5, "score" : [ 5, 1 ] }
// 每个条件都有元素可以匹配
db.students.find( { score: { $gt: 0, $lt: 2 } } )
// 返回的文档是
{ "_id" : 1, "score" : [ -1, 3 ] } // 3 -1
{ "_id" : 2, "score" : [ 1, 5 ] }// 1 1
{ "_id" : 3, "score" : [ 1, 5, 6 ] }// 1 1
{ "_id" : 5, "score" : [ 5, 1 ] }// 1 1
4. 数组单个元素匹配多个条件 注意和上面的区别 这里指的是数组中存在至少一个元素满足所有的条件。
// 样例数据
{ "_id" : 1, "score" : [ -1, 3 ] }
{ "_id" : 2, "score" : [ 1, 5 ] }
{ "_id" : 3, "score" : [ 1, 5, 6 ] }
{ "_id" : 4, "score" : [ 5, 6 ] }
{ "_id" : 5, "score" : [ 5, 1 ] }
// 至少一个元素满足所有条件
db.students.find( { score: { $elemMatch: { $gt: 0, $lt: 2 } } } )
// 返回的文档是
{ "_id" : 2, "score" : [ 1, 5 ] }// 1
{ "_id" : 3, "score" : [ 1, 5, 6 ] }// 1
{ "_id" : 5, "score" : [ 5, 1 ] }// 1
5. 建立索引
// 样例数据
{ _id: 1, item: "ABC", ratings: [ 2, 5, 9 ] }
{ _id: 2, item: "ABC", ratings: [ 3, 8, 9 ] }
// 对ratings字段建立索引
db.survey.createIndex( { ratings: 1 } )
#########################################################################
嵌套文档的数组:
// 样例数据
{
_id: 1,
name: "sue",
age: 19,
type: 1,
status: "P",
favorites: { artist: "Picasso", food: "pizza" },
finished: [ 17, 3 ],
badges: [ "blue", "black" ],
points: [
{ points: 85, bonus: 20 },
{ points: 85, bonus: 10 }
]
},
{
_id: 2,
name: "bob",
age: 42,
type: 1,
status: "A",
favorites: { artist: "Miro", food: "meringue" },
finished: [ 11, 25 ],
badges: [ "green" ],
points: [
{ points: 85, bonus: 20 },
{ points: 64, bonus: 12 }
]
},
{
_id: 3,
name: "ahn",
age: 22,
type: 2,
status: "A",
favorites: { artist: "Cassatt", food: "cake" },
finished: [ 6 ],
badges: [ "blue", "red" ],
points: [
{ points: 81, bonus: 8 },
{ points: 55, bonus: 20 }
]
},
{
_id: 4,
name: "xi",
age: 34,
type: 2,
status: "D",
favorites: { artist: "Chagall", food: "chocolate" },
finished: [ 5, 11 ],
badges: [ "red", "black" ],
points: [
{ points: 53, bonus: 15 },
{ points: 51, bonus: 15 }
]
},
{
_id: 5,
name: "xyz",
age: 23,
type: 2,
status: "D",
favorites: { artist: "Noguchi", food: "nougat" },
finished: [ 14, 6 ],
badges: [ "orange" ],
points: [
{ points: 71, bonus: 20 }
]
},
{
_id: 6,
name: "abc",
age: 43,
type: 1,
status: "A",
favorites: { food: "pizza", artist: "Picasso" },
finished: [ 18, 12 ],
badges: [ "black", "blue" ],
points: [
{ points: 78, bonus: 8 },
{ points: 57, bonus: 7 }
]
}
1. 组合元素满足查询条件 对于每一个条件都可以找到嵌套文档匹配
//
db.users.find( { 'points.points': { $lte: 55, "$gt": 80 } } )
//
{
"_id" : 3,
"name" : "ahn",
"age" : 22,
"type" : 2,
"status" : "A",
"favorites" : { "artist" : "Cassatt", "food" : "cake" },
"finished" : [ 6 ],
"badges" : [ "blue", "red" ],
"points" : [ { "points" : 81, "bonus" : 8 }, { "points" : 55, "bonus" : 20 } ]// 55 81
}
// 第一种情况
db.users.find( { points: { $elemMatch: { points: { $lte: 70, $gte: 56}} } } )
// 返回
{
"_id" : 2.0,
"name" : "bob",
"age" : 42.0,
"type" : 1.0,
"status" : "A",
"favorites" : {
"artist" : "Miro",
"food" : "meringue"
},
"finished" : [
11.0,
25.0
],
"badges" : [
"green"
],
"points" : [
{
"points" : 85.0,
"bonus" : 20.0
},
{
"points" : 64.0,// 64
"bonus" : 12.0
}
]
}
{
"_id" : 6.0,
"name" : "abc",
"age" : 43.0,
"type" : 1.0,
"status" : "A",
"favorites" : {
"food" : "pizza",
"artist" : "Picasso"
},
"finished" : [
18.0,
12.0
],
"badges" : [
"black",
"blue"
],
"points" : [
{
"points" : 78.0,
"bonus" : 8.0
},
{
"points" : 57.0,// 57
"bonus" : 7.0
}
]
}
// 第二种情况
db.users.find( { points: { $elemMatch: { points: { $lte: 70}, bonus: 20 } } } )
// 返回
{
"_id" : 3.0,
"name" : "ahn",
"age" : 22.0,
"type" : 2.0,
"status" : "A",
"favorites" : {
"artist" : "Cassatt",
"food" : "cake"
},
"finished" : [
6.0
],
"badges" : [
"blue",
"red"
],
"points" : [
{
"points" : 81.0,
"bonus" : 8.0
},
{
"points" : 55.0,// 55
"bonus" : 20.0// 20
}
]
}
// 意思就是说既要有文档第一个 也要有文档满足第二个
db.users.find( {"$and" : [
{ points: { $elemMatch: { points: { $lte: 70}, bonus: 20 } } },
{ points: { $elemMatch: { points: { $gt: 80}, bonus: 8 } } }
]} )
// 返回
{
"_id" : 3.0,
"name" : "ahn",
"age" : 22.0,
"type" : 2.0,
"status" : "A",
"favorites" : {
"artist" : "Cassatt",
"food" : "cake"
},
"finished" : [
6.0
],
"badges" : [
"blue",
"red"
],
"points" : [
{
"points" : 81.0,
"bonus" : 8.0
},
{
"points" : 55.0,
"bonus" : 20.0
}
]
}
// 也可以这么写 和上面的写法等价
db.users.find( { "points" : {"$all" : [
{ $elemMatch: { points: { $lte: 70}, bonus: 20 } },
{ $elemMatch: { points: { $gt: 80}, bonus: 8 } }
]}} )
// 返回
{
"_id" : 3.0,
"name" : "ahn",
"age" : 22.0,
"type" : 2.0,
"status" : "A",
"favorites" : {
"artist" : "Cassatt",
"food" : "cake"
},
"finished" : [
6.0
],
"badges" : [
"blue",
"red"
],
"points" : [
{
"points" : 81.0,
"bonus" : 8.0
},
{
"points" : 55.0,
"bonus" : 20.0
}
]
}