【Node.js】mongoose教程05--查詢

文章目錄
  1. 1. Model與Query
  2. 2. 查詢全部數據
  3. 3. 條件查詢
  4. 4. 條件查詢—數組
  5. 5. 組合條件查詢

本文的查詢是指存儲了5個手機數據後再查詢。存儲實現見文章:【Node.js】mongoose教程—存儲

GitHub源碼鏈接:sodino#MongoDemo


Model與Query

Model.find()方法會返回Query對象。

Model.find()方法原型如下:

1
2
3
4
5
6
7
8
9
10
11
12
Model.find(conditions, [projection], [options], [callback])
Finds documents
Parameters:
conditions <Object>
[projection] <Object> optional fields to return (http://bit.ly/1HotzBo)
[options] <Object> optional
[callback] <Function>
Returns:
<Query>

參數conditions是必填項,用於設定查詢條件。
參數projection是可選項,用於設定查詢結果的返回對象所包含的字段範圍。例如查詢的Phone返回的結果對象只包含device字段或去除device字段。詳情見鏈接$project (aggregation)
參數options是可選項,用於對查詢的結果做功能處理,如排序sort、數量限制limit、查詢跳躍skip等功能。詳情見鏈接Query.Options.
參數callback是可選項,用於獲取查詢結果。

該方法執行後,返回Query一個對象。
Query可以提供更加簡潔明瞭的查詢方法,這些查詢方法都與Model.find()中的參數conditionsprojectionoptions幾乎存在着一一對應的功能關係。
where() or() gte()conditionsselect()projectionsort() limit()options
Query也有一些功能擴展函數,如計算count()、排重distinct();也可以直接用於更新與刪除數據。

Query推薦使用鏈式調用的代碼編寫方式,在鏈式代碼的末尾調用.exec(callback)獲取查詢結果。
如以下代碼演示:

1
2
3
4
5
6
7
8
9
// 查詢:價格大於等於1000且小於等於4000,
// 且設備名稱包含大小寫不敏感的`huawei`,
// 並獲取該手機安裝的的前2個app
// chaining
Phone
.where('price').gte(1000).lte(4000)
.where('device', /^huawei/i)
.where('apps').slice(2)
.exec(callback)

下面來演示一些查詢的示例:


查詢全部數據

1
2
3
4
5
6
7
8
9
10
Phone.find((err, phones) => {
if (err) {
console.log('findAllPhone err:', err);
} else {
console.log('---findAllPhone---------------------------------------');
phones.forEach((element, index, phones) => {
console.log(index, element);
});
}

控制檯輸出:
findAllPhone


條件查詢

找出非智能手機:

1
2
3
4
5
6
7
8
9
10
11
12
function findNoSmartPhone() {
Phone.find({isSmart : false}).exec((err, phones) => {
console.log('---findNoSmartPhone()---------------------------------');
if (err) {
console.log(err);
} else {
phones.forEach((element, index, phones) => {
console.log(index, element);
});
}
});
}

控制檯輸出:
findNoSmartPhone


條件查詢—數組

在Phone中,有個apps中爲包含一個name字段的對象數組。定義如下:

1
2
3
4
5
6
// 開始定義Schema
var phoneSchema = new Schema({
... ...
apps : [{name : String}],
... ...
});

如果需要查找安裝了哪些手機安裝了Radio這個軟件,編寫條件爲{"apps.name" : "Radio"}可以這麼查詢:

1
2
3
4
5
6
7
8
9
10
11
12
function findPhoneInstalledRadio() {
Phone.find({'apps.name' : 'Radio'}).exec((err, phones)=>{
console.log('---findPhoneInstalledRadio()---------------------');
if (err) {
console.log(err);
} else {
phones.forEach((element, index, phones) => {
console.log(index, element);
})
}
});
}

控制檯輸出如下:

findPhoneInstalledRadio


組合條件查詢

在上面的兩個查詢演示了普通字段及數組下對象字段的指定條件查詢,但都是單條件查詢。
現在演示更加複雜的組合條件查詢。

即涉及到對比條件或邏輯條件的拼裝。

對比條件操作符(點擊查看詳情):

1
2
3
4
5
6
7
8
9
10
11
$eq // 相等
$ne // 不等於
$gt // 大於
$gte // 大於等於
$lt // 小於
$lte // 小於等於
$in // 屬於,處於
$nin // 不屬於,不處於

邏輯條件操作符(點擊查看詳情):

1
2
3
4
$or // 或
$and // 且
$not // 非
$nor // 對$or的條件取反,即$or的補集

以上的操作符可用直接用在Model.find()中的conditions參數中;當然Query類也提供了一一對應的查詢方法。
以下代碼演示組合條件: 查找中國或韓國廠商且價格處於[1000, 4000)範圍內的手機 
可以有如下4種查詢方式,它們的查詢結果是等價的。

方法1和方法3在Model.find()condictions參數直接使用運算操作符;
方法2和方法4使用Query.where().[chain_methods()].exec(callback)方式。
兩種方法是等價的,愛用哪個用哪個吧。

在本例子中,可以發現$or$in在某些場合是可以等價轉換的。
即以下兩種方式表達的意思都是指手機廠商是China或South Korea:

1
2
3
4
$or:[
{'manufacturer.country':'China'},
{'manufacturer.country':'South Korea'}
]
1
2
3
4
{
'manufacturer.country' :
{$in:['China', 'South Korea']}
}

接下來看4種方法的代碼實現:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// 方法1
Phone.find({$or:[
{'manufacturer.country':'China'},
{'manufacturer.country':'South Korea'}
], $and:[
{'price' : {$gte : 1000}},
{'price' : {$lt : 4000}}
]
}).exec((err, phones) => {
console.log('---findChina_or_SouthKorea_and_1000_4000Phone()----------------------------');
if (err) {
console.log(err);
} else {
phones.forEach((element, index, phones) => {
console.log(index, element);
});
}
});
// 方法2
Phone.find()
.or([{'manufacturer.country':'China'}, {'manufacturer.country':'South Korea'}])
.where('price').gte(1000).lt(4000)
.exec((err, phones) => {
console.log('---findChina_or_SouthKorea_and_1000_4000Phone()----------------------------');
if (err) {
console.log(err);
} else {
phones.forEach((element, index, phones) => {
console.log(index, element);
});
}
});
// 方法3
Phone.find({'manufacturer.country' :
{$in:['China', 'South Korea']},
$and:[
{'price' : {$gte : 1000}},
{'price' : {$lt : 4000}}
]
}).exec((err, phones) => {
console.log('---findChina_or_SouthKorea_and_1000_4000Phone()----------------------------');
if (err) {
console.log(err);
} else {
phones.forEach((element, index, phones) => {
console.log(index, element);
});
}
});
// 方法4
Phone.find()
.where('manufacturer.country').in(['China', 'South Korea'])
.where('price').gte(1000).lt(4000)
.exec((err, phones) => {
console.log('---findChina_or_SouthKorea_and_1000_4000Phone()----------------------------');
if (err) {
console.log(err);
} else {
phones.forEach((element, index, phones) => {
console.log(index, element);
});
}
});

控制檯輸出如下:
findChina_or_SouthKorea_and_1000_4000Phone


下一篇mongoose教程—排序


About Sodino

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章