MongoDB 练习 1

2025-09-09 00:00    #MongoDB   #Exercises  

5

  1. Write a MongoDB query to display all the restaurant which is in the borough Bronx.

这个简单,本质是查询固定的值

1db["restaurants"].find({'borough':'Bronx'})

8

  1. Write a MongoDB query to find the restaurants who achieved a score more than 90.

让我们查询一个数组,数组里面有一个Object的值>=0

1db["restaurants"].find({'grades.score': {$gt : 90}}).count()
1db["restaurants"].find({ 'grades' : {$elemMatch : { "score" :{$gt : 90} }  } })

这两个的结果是等价的,只不过第二个用到了数组匹配操作符$elemMatch

9

  1. Write a MongoDB query to find the restaurants that achieved a score, more than 80 but less than 100.

这个题目的意思是: grades里存在一个分数,这个分数在80与90之间

1db["restaurants"].find({ 'grades' : {$elemMatch : { "score" :{$gt : 80,$lt:100} }  } })

10

  1. Write a MongoDB query to find the restaurants which locate in latitude value less than -95.754168.

这里考察我们如何查询数组里某个下标的值

1db.restaurants.find({"address.coord.0":{$lte :  -95.754168} })

11

  1. Write a MongoDB query to find the restaurants that do not prepare any cuisine of ‘American’ and their grade score more than 70 and latitude less than -65.754168.
1db["restaurants"].count({cuisine:{$not: {$regex: /.*American.*/ } },grades:{$elemMatch : { "score":{$gte:70} }} })

这里考查我们有多个条件,同时成立的查询

发现一个问题:

我查询了文档

$ne操作在数组的查询与我想的不一样

如果你希望能够匹配数组中有部分元素与 “red” 不匹配的文档,可以使用 $elemMatch 来精确匹配数组中的单个元素:

1db.newdb.find({
2  tags: { $elemMatch: { $ne: "red" } }
3})

这里官方给出的答案

1db.restaurants.find(
2               {$and:
3                    [
4                       {"cuisine" : {$ne :"American "}},
5                       {"grades.score" : {$gt : 70}},
6                       {"address.coord" : {$lt : -65.754168}}
7                    ]
8                });

12

  1. Write a MongoDB query to find the restaurants which do not prepare any cuisine of ‘American’ and achieved a score more than 70 and located in the longitude less than -65.754168. Note : Do this query without using $and operator.

和上一个问题的问题一样,只是不让我们使用$and$符号

1db.restaurants.find(
2                           {
3                             "cuisine" : {$ne : "American "},
4                             "grades.score" :{$gt: 70},
5                             "address.coord" : {$lt : -65.754168}
6                            }
7                     );

13

  1. Write a MongoDB query to find the restaurants which do not prepare any cuisine of ‘American’ and achieved a grade point ‘A’ not belongs to the borough Brooklyn. The document must be displayed according to the cuisine in descending order.

前面的条件还好,这里只是多了一个排序的要求

1db.restaurants.find( {
2                             "cuisine" : {$ne : "American"},
3                             "grades.grade" :"A",
4                             "borough": {$ne : "Brooklyn"}
5                       } 
6                    ).sort({"cuisine":-1});

14

  1. Write a MongoDB query to find the restaurant Id, name, borough and cuisine for those restaurants which contain ‘Wil’ as first three letters for its name.

查询的条件是name的首个三个字母是3个Wil字符.

我这里的写法与官方不一样,因为我不理解官方的第二个参数,为什么这样写,因为我查询的nodejs api 不是这样的.

https://mongodb.github.io/node-mongodb-native/6.11/interfaces/FindOptions.html#projection

1db["restaurants"].find ({name:/AWil/}).projection({name:1,restaurant_id:1,borough:1,cuisine:1}})

为什么会这样? ,AI 告诉我这是一个差异!!!

你提出的问题涉及到 MongoDB Node.js Driverfind 方法的第二个参数,它实际上是一个 选项对象(options),而 投影(projection) 是该选项对象中的一个字段。这是 MongoDB Node.js DriverMongoDB Shellmongosh)之间的一个差异。

MongoDB Node.js Driver 的 find 方法

根据你提供的链接,在 MongoDB 的 Node.js Driver 版本 3.6 中,find 方法的第二个参数 必须是一个选项对象,该对象中可以包含多个选项,例如 projection, sort, limit 等。

find 方法的签名(Node.js Driver)

1find(filter, options)

投影(Projection)在选项对象中

MongoDB Node.js Driver 中,投影(projection) 是通过选项对象中的 projection 字段来指定的。因此,第二个参数的形式通常是一个包含 projection 字段的对象,而 投影(projection) 本身是一个文档,定义了需要包含或排除的字段。

示例代码:

 1const { MongoClient } = require('mongodb');
 2
 3async function queryRestaurants() {
 4  const client = new MongoClient('mongodb://localhost:27017');
 5  await client.connect();
 6  const db = client.db('test'); // 假设你的数据库名是 'test'
 7  const collection = db.collection('restaurants');
 8
 9  // 使用 find 查询并投影
10  const cursor = collection.find(
11    { name: /^Wil/ },
12    {
13      projection: {
14        "restaurant_id": 1,
15        "name": 1,
16        "borough": 1,
17        "cuisine": 1
18      }
19    }
20  );
21
22  // 获取查询结果并打印
23  const results = await cursor.toArray();
24  console.log(results);
25
26  await client.close();
27}
28
29queryRestaurants().catch(console.error);

为什么必须使用 projection 字段?

在 Node.js MongoDB Driver 的 find 方法中,第二个参数是一个 选项对象(options),因此你需要明确指定 projection 字段来设置查询返回的字段。这是与 MongoDB Shell(mongosh) 的差异,后者可以直接将投影文档作为第二个参数。

Node.js Driver 的选项对象结构

在 Node.js 中,你可以传递一个包含多个选项字段的对象,例如:

1{
2  projection: { "restaurant_id": 1, "name": 1, "borough": 1, "cuisine": 1 },
3  sort: { name: 1 },
4  limit: 10
5}

总结

MongoDB Node.js Driver 中,第二个参数是一个 选项对象(options),其中包含 projection 字段来指定投影。而在 MongoDB Shell(mongosh) 中,第二个参数直接是一个投影文档,可以省略 projection 字段名。

Node.js Driver 使用 projection

1db.restaurants.find(
2  { name: /^Wil/ },
3  { projection: { "restaurant_id": 1, "name": 1, "borough": 1, "cuisine": 1 } }
4);

MongoDB Shell 中直接传递投影文档:

1db.restaurants.find(
2  { name: /^Wil/ },
3  { "restaurant_id": 1, "name": 1, "borough": 1, "cuisine": 1 }
4);

好吧,经过我的查询,这真的是一个差异:

两者确实不一样.

15

  1. Write a MongoDB query to find the restaurant Id, name, borough and cuisine for those restaurants which contain ‘ces’ as last three letters for its name.

和上一个问题一样,但是要查询的值是最后三个字符,还是使用regex

1db.restaurants.find(
2{name: /ces$/},
3{
4"restaurant_id" : 1,
5"name":1,"borough":1,
6"cuisine" :1
7}
8);
1db["restaurants"].find ({name:/ces$/}).projection({name:1,
2restaurant_id:1,borough:1,cuisine:1})

16 包含Reg+投影

  1. Write a MongoDB query to find the restaurant Id, name, borough and cuisine for those restaurants which contain ‘Reg’ as three letters somewhere in its name.

改变一下reg就可以了.

 1db["restaurants"].find({name:/Reg/},{name:1}).count()
 2db["restaurants"].find({name:/Reg/},{name:1}).count()
 3
 4db.restaurants.find(
 5{"name": /.*Reg.*/},
 6{
 7"restaurant_id" : 1,
 8"name":1,"borough":1,
 9"cuisine" :1
10}
11);

17

  1. Write a MongoDB query to find the restaurants which belong to the borough Bronx and prepared either American or Chinese dish.
1db["restaurants"].find({"cuisine": {$in :['Chinese', 'American ']} ,
2  "borough": "Bronx"
3},{"cuisine":1}).count()
1db.restaurants.find(
2{
3"borough": "Bronx" ,
4$or : [
5{ "cuisine" : "American " },
6{ "cuisine" : "Chinese" }
7]
8}
9);

18

Write a MongoDB query to find the restaurant Id, name, borough and cuisine for those restaurants which belong to the borough Staten Island or Queens or Bronxor Brooklyn.

和我的上一个执行$in的语法一样

1db.restaurants.find(
2    {"borough" :{$in :["Staten Island","Queens","Bronx","Brooklyn"]}},
3    {
4    "restaurant_id" : 1,
5    "name":1,"borough":1,
6    "cuisine" :1
7    }
8    );

19

Write a MongoDB query to find the restaurant Id, name, borough and cuisine for those restaurants which are not belonging to the borough Staten Island or Queens or Bronxor Brooklyn.

从数理逻辑的角度来看,a{borough Staten Island , Queens , Bronxor Brooklyn}a \notin \{\text{borough Staten Island , Queens , Bronxor Brooklyn} \} 当这个条件为true的时候,这里使用$nin操作

1db.restaurants.find(
2{"borough" :{$nin :["Staten Island","Queens","Bronx","Brooklyn"]}},
3{
4"restaurant_id" : 1,
5"name":1,"borough":1,
6"cuisine" :1
7}
8);

20

Write a MongoDB query to find the restaurant Id, name, borough and cuisine for those restaurants which achieved a score which is not more than 10.

这里的核心就在于 not more than 10 ,数学写法

¬(grades.score>10)grades.score<=10 \neg (grades.score > 10) \Leftrightarrow grades.score <= 10
1db["restaurants"].find({"grades.score": {$lte: 10}}).count()
2
3db.restaurants.find( {"grades.score" : { $not: {$gt : 10} } }).count()

恩……….., 两者竟然是不一样的.

题目应该问的是: 所有的分都不超过10.

$lte:10 应该是只要有一个(存在)<=10 就成立

遇到这种事件,应该首先查文档: https://www.mongodb.com/zh-cn/docs/manual/reference/operator/query/not/,但文档上没有说.

find({ "grades.score": {$gt : 10} }) 表示的意思其实是: (x>10)\exists (x > 10)

find({ "grades.score": {$not :{ $gt : 10} }}) 表示的意思其实是: ¬(x>10)(x<=10)\neg \exists (x > 10) \to \forall (x<=10),这样就能理解了