7).对内置数组中文档的查询,$elemMatch
对内置数组中文档的查询其实就是将内置数组中的元素替换成文档形式,$elemMatch保证我们的查询是在内置数组中同一文档中进行的,如:
> db.grade.find()
{
"_id" : ObjectId("53a3f4d933c516902a43a7a4"),
"name" : "jim",
"age" : 20,
"score" : [
{
"course" : "computer",
"credit" : 2,
"teacher" : "mary"
},
{
"course" : "english",
"credit" : 1,
"teacher" : "join"
}
]
}
{
"_id" : ObjectId("53a3fbf7901e10bdd70adf9e"),
"name" : "amy",
"age" : 21,
"score" : [
{
"course" : "computer",
"credit" : 2,
"teacher" : "nola"
},
{
"course" : "chinese",
"credit" : 3,
"teacher" : "mary"
}
]
}
方式一、这里指定score中course为computer和teacher为mary是查不到的
> db.grade.find({"score" : {"course" : "computer", "teacher" : "mary"}})
方式二、指定score中元素的全部字段就能查到了,而且顺序不能变
> db.grade.find({"score" : {"course" : "computer", "teacher" : "mary", "credit" : 2}})
> db.grade.find({"score" : {"course" : "computer", "credit" : 2, "teacher" : "mary"}})
{
"_id" : ObjectId("53a3f4d933c516902a43a7a4"),
"name" : "jim",
"age" : 20,
"score" : [
{
"course" : "computer",
"credit" : 2,
"teacher" : "mary"
},
{
"course" : "english",
"credit" : 1,
"teacher" : "join"
}
]
}
方式三、指定score.course为computer和score.teacher为mary居然把两个都查出来了
> db.grade.find({"score.course" : "computer", "score.teacher" : "mary"})
{
"_id" : ObjectId("53a3f4d933c516902a43a7a4"),
"name" : "jim",
"age" : 20,
"score" : [
{
"course" : "computer",
"credit" : 2,
"teacher" : "mary"
},
{
"course" : "english",
"credit" : 1,
"teacher" : "join"
}
]
}
{
"_id" : ObjectId("53a3fbf7901e10bdd70adf9e"),
"name" : "amy",
"age" : 21,
"score" : [
{
"course" : "computer",
"credit" : 2,
"teacher" : "nola"
},
{
"course" : "chinese",
"credit" : 3,
"teacher" : "mary"
}
]
}
方式四、通过$elemMatch来查询,得到我们想要的结果
> db.grade.find({"score" : {"$elemMatch" : {"course" : "computer", "teacher" : "mary"}}})
{
"_id" : ObjectId("53a3f4d933c516902a43a7a4"),
"name" : "jim",
"age" : 20,
"score" : [
{
"course" : "computer",
"credit" : 2,
"teacher" : "mary"
},
{
"course" : "english",
"credit" : 1,
"teacher" : "join"
}
]
}
对于方式一和方式二可能有个难理解的地方,为什么只指定其中部分字段就查询不到,而必须要指定全部的字段才可以呢,查询内置数组的时候只要指定fruit为apple就能查询出包含apple的数组,这里为什么要指定全部的字段呢。其实这是一个误区,在这里一个内置文档才相当于fruit中的一种水果,也就是数组中的一个元素,如果连这个元素都缺斤少两,在数组中如何查询的到呢。
对于方式三,指定score.course和score.teacher为啥把两个都查询出来了,明明第二个结果不是我们想要的,course为computer时teacher并不为mary,但是course为chinese时teacher为mary,所以第二个结果中的确存在score.course为computer,并且同时存在score.teacher为mary,那这是将两个文档的字段组合起来达到我们的要求了。显然这并不是我们想要的,所以就必须使用$elemMatc,也就是方式四,它保证了我们查询是在数组中同一个文档元素中进行的。
7).$where
$where可以执行任何的java script作为查询的一部分,所以$where几乎可以做所有的事,但是这种方式必须要将每个文档从BSON转换成java script对象,然后再通过$where的表达式来执行,而且还不能用索引。因此用$where是下下策,在你实在走投无路的时候再用。用法也比较简单,就是对this的操作,如果某文档满足我们自定义的条件就返回true,那么该文档就会被返回,如:
> db.fruit.find()
{ "_id" : Objec