深入理解mongodb查詢條件語句

龍恩0707發表於2018-11-18

閱讀目錄

1. 理解:"$lt"、"$lte"、"$gt" 和 "$gte"

首先在講解查詢條件之前,我們先看看我們的資料庫中有哪些基本的資料,我們可以使用如下程式碼查詢下:如下程式碼:

const mongo = require('mongodb');
const Server = mongo.Server;
const Db = mongo.Db;

const server = new Server('localhost', '27017', { auto_reconnect: true });
const db = new Db('dataDb', server, { safe: true });

db.open(function(err, db) {
  if (err) {
    throw err;
  } else {
    console.log('成功建立資料庫連線');
    db.collection('users', function(err, collection) {
      if (err) {
        throw err;
      } else {
        // 開始查詢集合users
        collection.find({}).toArray(function(err, docs) {
          if (err) {
            throw err;
          } else {
            console.log(docs);
            db.close();
          }
        });
      }
    });
  }
});

如下圖所示:

"$lt"、"$lte"、"$gt" 和 "$gte" 分別對應 <、<=、> 和 >=. 可以將其組合起來查詢一個範圍的值。
現在我們想查詢年齡在 30歲到40歲的使用者,就可以使用如下命令了,如下程式碼:

collection.find({"age" : {"$gte": 30, $lte: 40}});

所有程式碼如下:

const mongo = require('mongodb');
const Server = mongo.Server;
const Db = mongo.Db;

const server = new Server('localhost', '27017', { auto_reconnect: true });
const db = new Db('dataDb', server, { safe: true });

db.open(function(err, db) {
  if (err) {
    throw err;
  } else {
    console.log('成功建立資料庫連線');
    db.collection('users', function(err, collection) {
      if (err) {
        throw err;
      } else {
        // 開始查詢集合users
        collection.find({"age" : {"$gte": 30, $lte: 40}}).toArray(function(err, docs) {
          if (err) {
            throw err;
          } else {
            console.log(docs);
            db.close();
          }
        });
      }
    });
  }
});

執行結果為:

注意: 下面的查詢我只會寫一句程式碼哦,其他的程式碼和上面程式碼一樣,比如查詢程式碼,只會寫這麼一句:
collection.find({"age" : {"$gte": 30, $lte: 40}}),為了節約篇幅。

2. 理解 '$ne'

$ne' 的含義是,文件的鍵值不等於某個特定值,它的含義是 表示 '不相等的意思'。比如我現在想查詢 名字不等於 'kongzhi'.

首先我們資料庫還是有如下資料:

我們可以像如下查詢:

collection.find({"name" : {"$ne": 'kongzhi'}})

含義是查詢文件後,不包含 name = "kongzhi" 的所有資料,執行結果可以看到如下:

3. 理解 "$in" 和 "$or", 及 "$nin"

Mongodb中有兩種方式進行or查詢,"$in" 可以用來查詢一個鍵的多個值;"$or" 可以在多個鍵中查詢任意的給定值。

那麼他們有什麼區別呢?
1)'$in' 可以理解為 '包含的意思',比如說,我想查詢 name 包含 'longen1' 和 'longen2' 這兩個值的話,可以使用 '$in'
進行查詢。比如如下查詢語句:

collection.find({"name" : {"$in": ['longen1', 'longen2']}})

執行結果如下所示:

2)'$nin': 和 '$in' 相對應的是 '$nin', '$nin' 將返回與陣列中所有條件都不匹配的文件。比如說,我想返回資料不包含 'longen1' 和 'longen2' 的資料,可以使用如下命令:

collection.find({"name" : {"$nin": ['longen1', 'longen2']}})

執行結果如下所示:

3)'$or' 的含義是 '或者的意思',就是說 我既要查詢到 name='longen1', 還要查詢到 name='kongzhi1' 這樣的資料,就可以使用 '$or'了,'$or' 接受一個包含所有條件的陣列作為引數。比如如下執行命令:

collection.find({"$or": [{"name": 'longen1'}, {"name": 'kongzhi1'}]})

執行結果如下所示:

4. 理解使用正規表示式來查詢

正規表示式能夠靈活有效地匹配字串,比如說我想查詢所有名為 "long" 的使用者,可以如下執行程式碼:

collection.find({"name": /long/i});

查詢結果如下所示:

它可以模糊匹配到所有name欄位含有 'long' 的字串的,再比如,我匹配查詢所有含有 'kong' 字串的,執行程式碼如下:

collection.find({"name": /kong/i});

查詢結果如下所示:

注意:使用正則匹配的方式和我們的javascript的正則匹配是一模一樣的語法。也就是說 相容Perl的正規表示式的語法。

5. 理解查詢陣列 $all, $size 操作符的使用

5.1) $all: 該操作符的含義是使用多個元素來模糊匹配陣列,也就是說,如果多個陣列裡麵包含 $all 匹配的內容的話,那麼該陣列都會被匹配出來。

假如現在users集合裡面有如下資料:

我現在想匹配 "name": ['kongzhi', 'tugenhua'] 這樣的,把陣列同時包含這兩個資料的陣列匹配出來,可以如下程式碼:

collection.find({"name": {$all: ['kongzhi', 'tugenhua']}})

執行結果如下:

如上也可以對整個陣列進行精確匹配。

但是如果想查詢陣列特定位置的元素,需要使用 key.index 語法指定下標:如下程式碼:

collection.find({"name.0": 'kongzhi1'});

陣列的下標都是從0開始的,所以上面的表示式會使用陣列的第一個元素 和 kongzhi1 進行匹配。如下匹配的結果:

5.2)$size

該操作符的含義是 查詢特定長度的陣列。如下程式碼:

collection.find({"name": {"$size": 3}})

它的含義是 查詢 name欄位的陣列長度為3的。查詢結果如下:

如果我們現在把查詢的長度改為1或者2的話,比如如下程式碼:

collection.find({"name": {"$size": 1}})

那麼它就會什麼都不能匹配到,如下所示:

6. 理解 limit, skip 和 sort

6.1) limit: 該操作符是限制結果數量的含義,可以在find後使用 limit函式,比如整個users集合裡面有如下資料:

一共有6條資料。

現在我們使用limit函式,比如限制只返回3條資料,程式碼可以如下寫:

collection.find().limit(3).toArray(function(err, docs) {})

執行結果如下所示:

limit指上限,可以理解為返回最多3個,但是如果資料庫集合裡面資料沒有3個的話,那麼就會返回匹配數量的結果。

6.2) skip 該操作符的含義是 跳過集合中的多少個資料,然後返回集合中剩下的資料,比如如下匹配程式碼:

collection.find().skip(3).toArray(function(err, docs) {})

它會跳過集合中三個資料,然後返回集合中剩餘的資料,執行結果如下所示:

6.3)sort, 該操作符接收一個物件作為引數,這個物件是一組 鍵/值對,鍵對應集合中的鍵名,值代表排序的方向,排序的方向可以是1(升序),或者 -1(降序)。如果指定了多個鍵,則按照這些鍵被指定的順序逐個排序。

比如我們現在想要按照 age 降序,程式碼可以如下寫:

collection.find().sort({age: -1}).toArray(function(err, docs) {})

執行結果如下所示:

7. 實現分頁:

7.1)使用skip進行分頁:如上三個操作符可以組合使用,對於分頁來說非常有用,比如我想每頁返回2條資料,並且按age從高到底進行排序;可以如下寫程式碼:

collection.find().limit(2).sort({age: -1}).toArray(function(err, docs) {})

執行結果如下所示:

當我們點選下一頁的時候,可以檢視更多的結果,我們可以通過skip實現,只需要跳過前面2條資料就好了。

collection.find().limit(2).skip(2).sort({age: -1}).toArray(function(err, docs) {})

執行結果如下:

因此我們可以簡單這樣實現一個分頁,根據傳進來的頁碼及一頁多少條來判斷。比如我們預設一頁10條資料,然後預設跳過0條,就是第一頁的資料,如果使用者傳遞進來當前的頁碼是2,每頁的條數是20條的話,那麼就使用使用者傳遞進來的引數進行操作。

var page = 1,
pagesize = 10;

if ('使用者傳進來的頁碼') {
   page = '使用者傳進來的頁碼'
}

if ('用來傳進來的頁碼大小') {
   pagesize = '使用者傳進來的頁碼大小';
}

/*
跳過多少條的邏輯: 如果當前的頁碼是第一頁的話,那麼就跳過0條;
如果當前的頁碼是大於1的話,比如第2頁,那麼跳過的條數是 (2-1) * 一頁多少條資料
skipCount(跳過的條數的計算方式) = (page - 1) * pagesize;
*/

因此執行分頁的程式碼如下:

collection.find().limit(pagesize).skip(skipCount).sort({age: -1}).toArray(function(err, docs) {})

注意:skip進行分頁有缺點的,如果使用skip跳過很多條資料的時候,查詢的速度會變得非常慢,因為我們先要找到需要被跳過
的資料,然後再拋棄這些資料。因此我們不要使用skip對結果分頁的。

相關文章