Mongoose教程翻譯

原文地址

本文簡(jiǎn)單的介紹了數(shù)據(jù)庫(kù),以及如何在 Node/Express 中應(yīng)用他們祝懂。之后展示如何使用Mongoose為一個(gè)圖書(shū)網(wǎng)站提供數(shù)據(jù)訪問(wèn)紊扬。介紹了Mongoose的模式和模型的聲明照瘾,主要屬性類(lèi)型,基礎(chǔ)校驗(yàn)器飘蚯。也展示了訪問(wèn)數(shù)據(jù)模型的幾種主要方法馍迄。

概括


圖書(shū)管理員將使用一個(gè) 圖書(shū)管理網(wǎng)站 去記錄書(shū)籍和借書(shū)人的信息,同時(shí)讀者會(huì)使用 圖書(shū)管理網(wǎng)站 去瀏覽搜索圖書(shū)局骤,去查看是不是某書(shū)全部借出攀圈,然后預(yù)約或直接借走該書(shū)。為了更有效率存儲(chǔ)信息峦甩,這里我們需要一個(gè)數(shù)據(jù)庫(kù)赘来。

Express提供了多種數(shù)據(jù)庫(kù)的支持,你有多種方式去實(shí)現(xiàn)增刪查改操作凯傲。本文簡(jiǎn)要的概述了一些可用的選項(xiàng)犬辰,并詳細(xì)說(shuō)明一些查詢(xún)的特殊機(jī)制。

使用什么數(shù)據(jù)庫(kù)冰单?

Express應(yīng)用可以使用Node支持的各種數(shù)據(jù)庫(kù)(Express本身對(duì)數(shù)據(jù)庫(kù)并沒(méi)有特殊要求)幌缝。常用的選項(xiàng)包括PostgreSQL,MySQL球凰,Redis狮腿,SQLite,MongoDB呕诉。

當(dāng)選擇一個(gè)數(shù)據(jù)庫(kù)時(shí)缘厢,我們需要考慮的常常有 時(shí)間成本,學(xué)習(xí)曲線甩挫,性能贴硫,備份和回滾的易用性,成本以及其社區(qū)支持情況伊者。雖然并沒(méi)有一個(gè)最好的數(shù)據(jù)庫(kù)英遭,但是對(duì)于我們的 圖書(shū)管理網(wǎng)站 這樣的小型網(wǎng)站,任何流行的數(shù)據(jù)庫(kù)都是可以的亦渗。

如何更好的與數(shù)據(jù)庫(kù)交互挖诸?

與數(shù)據(jù)庫(kù)交互有兩種方法:

  1. 使用數(shù)據(jù)庫(kù)的自帶的查詢(xún)語(yǔ)言(比如SQL)
  2. 使用對(duì)象數(shù)據(jù)模型("ODM")或?qū)ο箨P(guān)系模型 ("ORM")。一個(gè)ODM或ORM對(duì)象代表的就是一個(gè)映射到底層數(shù)據(jù)庫(kù)的數(shù)據(jù)對(duì)象比如說(shuō)JSON對(duì)象法精。一些ORM對(duì)象是指定數(shù)據(jù)庫(kù)的多律,一些則不然。

使用SQL語(yǔ)言或者其他數(shù)據(jù)庫(kù)支持的語(yǔ)言可以獲得很好的性能搂蜓。ODM則相對(duì)比較慢狼荞,因?yàn)樾枰a去轉(zhuǎn)換映射的對(duì)象和數(shù)據(jù)庫(kù)中的格式,所以他生成的查詢(xún)語(yǔ)句可能不夠高效(尤其是在ODM為了支持不同的數(shù)據(jù)庫(kù)后臺(tái)帮碰,這時(shí)必須對(duì)數(shù)據(jù)庫(kù)功能做出極大的妥協(xié))相味。

使用ODM的優(yōu)勢(shì)在于程序員可以一直關(guān)注與JavaScript 對(duì)象而不是數(shù)據(jù)庫(kù)語(yǔ)義,尤其是在你需要和不同的數(shù)據(jù)庫(kù)交互(可能是同一應(yīng)用殉挽,或不同應(yīng)用)丰涉。ODM也提供了清晰方式去校驗(yàn)檢查數(shù)據(jù)拓巧。

使用ODM或ORM可以降低開(kāi)發(fā)和維護(hù)成本,除非你非常擅長(zhǎng)原生查詢(xún)語(yǔ)言昔搂,或?qū)π阅芤蠛芨吡嵯駝t你都應(yīng)該優(yōu)先考慮使用ODM或ORM。

使用什么ODM/ORM

在npm中有許多ODM摘符、ORM贤斜。

在本文寫(xiě)作時(shí)幾個(gè)熱門(mén)的框架

  • Mongoose:Mongoose是一個(gè)用于異步環(huán)境的MongoDB的對(duì)象模型。
  • Waterline:提取自基于Express的Sail框架的對(duì)象關(guān)系模型逛裤。他為眾多數(shù)據(jù)庫(kù)提供了統(tǒng)一的API接口瘩绒,包括 Redis, mySQL, LDAP, MongoDB, 和 Postgres。
  • Bookshelf:同時(shí)具備promise和傳統(tǒng)回調(diào)函數(shù)的接口带族,提供了對(duì)事務(wù)的支持锁荔,eager/nested-eager relation loading(不知道咋翻),集成多態(tài)蝙砌,支持 一對(duì)一阳堕,一對(duì)多,多對(duì)多關(guān)系择克。支持PostgreSQL, MySQL, 和 SQLite3恬总。
  • Objection:盡可能的簡(jiǎn)化的使用數(shù)據(jù)庫(kù)和SQL的全部功能(支持SQLite3, Postgres 和 MySQL)
  • Sequelize:基于promise的ORM...

在選擇解決方案時(shí)一般應(yīng)該考慮他們都提供哪些功能,以及他們社區(qū)的活躍度(下載肚邢,捐款壹堰,Bug報(bào)告,文檔質(zhì)量)骡湖。在此文寫(xiě)作時(shí)Mongoose當(dāng)前最受歡迎的ORM贱纠,如果你在你的應(yīng)用中使用MongoDB作為你的數(shù)據(jù)庫(kù),那么他是一個(gè)合理的選擇响蕴。

在LocalLibrary(這篇文章中的項(xiàng)目名)使用MongoDB和Mongoose

在本文中我們使用Mongoose來(lái)訪問(wèn)我們的圖書(shū)數(shù)據(jù)谆焊。Mongoose作為MongoDB的前端,MongoDB是一個(gè)開(kāi)源的NoSQL浦夷,使用面向文檔的對(duì)象模型的數(shù)據(jù)庫(kù)懊渡。在MongoDB中 集合(collection)中的文檔(documents)類(lèi)似于關(guān)系數(shù)據(jù)庫(kù)中的表(table)中的行(row)。

這對(duì)ODM和數(shù)據(jù)庫(kù)組合在Node的社區(qū)中是非常流行的军拟,部分原因是因?yàn)槲臋n存儲(chǔ)和查詢(xún)起來(lái)非常類(lèi)似于JSON,對(duì)于JS程序員這是非常熟悉的誓禁。

你不必為了使用Mongoose而去了解MongoDB懈息,但是如果你已經(jīng)了解MongoDB,可以更容易的使用和理解Mongoose

教程后續(xù)部分將講解如何為L(zhǎng)ocalLibrary定義以及使用Mongoose模板和模型摹恰。

LocalLibrary的model設(shè)計(jì)


當(dāng)你開(kāi)始進(jìn)行model編碼的時(shí)候辫继,花一些時(shí)間考慮你應(yīng)該需要存儲(chǔ)什么數(shù)據(jù)怒见,以及不同對(duì)象之間的關(guān)系。

我們知道我們需要存儲(chǔ)有關(guān)書(shū)籍的信息(書(shū)名姑宽,概要遣耍,作者,類(lèi)型炮车,書(shū)號(hào))舵变,而且一種書(shū)我們可能有多本(擁有唯一的ID,可用狀態(tài))瘦穆,我們可能也需要存儲(chǔ)除了姓名之外其他的作者信息纪隙,而且可能會(huì)有多個(gè)作者名是相同或相似的。我們還想能夠通過(guò) 書(shū)名扛或,作者绵咱,書(shū)的類(lèi)別進(jìn)行排序。

當(dāng)你設(shè)計(jì)你的Model時(shí)為不同的Object(擁有一組相關(guān)的信息的對(duì)象)設(shè)置不同的Model是必要的熙兔。在當(dāng)前的實(shí)例中明顯的對(duì)象有 書(shū)籍悲伶,書(shū)籍實(shí)體,作者住涉。

你可能也想為一個(gè)下拉列表選項(xiàng)新建一個(gè)Model麸锉。相對(duì)于硬編碼,當(dāng)下拉列表不確定或經(jīng)常更改秆吵,這種方式更加推薦淮椰。在本例中書(shū)籍類(lèi)型(科幻小說(shuō),法國(guó)詩(shī)歌)明顯就是屬于這種類(lèi)型纳寂。

一旦我們確定了Model和相應(yīng)的屬性主穗,我們就需要思考他們之間的關(guān)系。

考慮到這一點(diǎn)毙芜,下面的UML關(guān)系圖展示了當(dāng)前我們定義的Model迈喉。根據(jù)上文的討論,我們將為書(shū)籍(包含書(shū)籍的一般信息)艘绍,書(shū)籍實(shí)體(包含這本書(shū)在系統(tǒng)中的狀態(tài))侥猩,作者 創(chuàng)建Model。同時(shí)我們也決定為書(shū)籍的類(lèi)別創(chuàng)建一個(gè)Model隘冲,這樣書(shū)的類(lèi)別就可以動(dòng)態(tài)修改闹瞧。書(shū)籍實(shí)體的狀態(tài)并不常變化,我們不會(huì)為他單獨(dú)創(chuàng)建Model展辞。在每個(gè)方塊中我們定義了Model的名字奥邮,以及屬性名和類(lèi)型,還有方法名和方法返回值的類(lèi)型。

該圖也展示了Model直接的關(guān)系洽腺,和他們數(shù)量的對(duì)應(yīng)關(guān)系(最大和最薪潘凇)。比如在Book和Genre之間的連線蘸朋,在靠近Book的數(shù)字表示一本書(shū)有0或者多個(gè)Genre核无,而另一端的數(shù)字表示每個(gè)Genre有0或者多個(gè)Book

天殺的UML圖

Mongoose入門(mén)


這部分概括了如何用Mongoose連接MongoDB,如何定義Schema(這個(gè)之前被我翻成模板藕坯,不知道對(duì)不對(duì)团南,后面索性不返了) 和Model,如何進(jìn)行簡(jiǎn)單的查詢(xún)堕担。

安裝Mongoose和MongoDB

Mongoose和其他的依賴(lài)一樣被安裝已慢,使用以下命令為你的項(xiàng)目安裝Mongoose。

npm install mongoose --save

安裝Mongoose會(huì)自動(dòng)加入他的依賴(lài)霹购,例如MongoDB的驅(qū)動(dòng)佑惠,但并沒(méi)有安裝MongoDB數(shù)據(jù)庫(kù)本身。如果你想要安裝MongoDB你可以從這里下載多個(gè)平臺(tái)的安裝包齐疙。你也可以使用云端的MongoDB實(shí)例膜楷。

提示:在本文中我們將使用mLab的云端作為數(shù)據(jù)庫(kù)。這樣非常適合開(kāi)發(fā)贞奋,對(duì)于這個(gè)教程這樣做也是有意義的赌厅,因?yàn)樗拱惭b過(guò)程不依賴(lài)讀者的操作系統(tǒng)。

連接到MongoDB

Mongoose會(huì)向MongoDB請(qǐng)求連接轿塔。你能夠使用require()引入Mongoose特愿,并使用mongoose.connect()連接到本地?cái)?shù)據(jù)庫(kù),如下所示:

//Import the mongoose module
var mongoose = require('mongoose');

//Set up default mongoose connection
var mongoDB = 'mongodb://127.0.0.1/my_database';
mongoose.connect(mongoDB);

//Get the default connection
var db = mongoose.connection;

//Bind connection to error event (to get notification of connection errors)
db.on('error', console.error.bind(console, 'MongoDB connection error:'));

用mongoose.connection你可以獲得Mongoose的默認(rèn)Connection 對(duì)象勾缭。一旦連接完成揍障,open 事件將從Connection 實(shí)例中發(fā)射。

提示:如果你需要額外的Connection俩由,你可以使用mongoose.createConnection()毒嫡,他接受一個(gè)和connect()相同格式的數(shù)據(jù)庫(kù)URI(包含host,數(shù)據(jù)庫(kù)名幻梯,端口兜畸,選項(xiàng)),返回一個(gè)Connection 實(shí)例碘梢。

定義并創(chuàng)建Model

Model是使用Schema 接口來(lái)定義咬摇。Schema 用來(lái)定義存儲(chǔ)在document 中的屬性,并且賦予他們校驗(yàn)的規(guī)則煞躬,和默認(rèn)值肛鹏。另外你可以定義靜態(tài) 或 實(shí)體 的helper方法,使你的數(shù)據(jù)類(lèi)型更加易于使用。你也可以定義像其他屬性一樣使用的虛擬屬性龄坪,這些屬性并不會(huì)被保存到數(shù)據(jù)庫(kù)中(這些會(huì)在后文中講解)。

Schema使用mongoose.model()去“編譯”入Model复唤。一旦擁有一個(gè)model 健田,你可以使用他用來(lái)創(chuàng)建,查詢(xún)佛纫,刪除指定的對(duì)象妓局。

Model對(duì)應(yīng)的是MongoDB中documents的collection,documents中包含在Schema中的定義的屬性和屬性對(duì)應(yīng)的類(lèi)型呈宇。

定義Schema

下面的代碼展示了如何定義一個(gè)簡(jiǎn)單的Schema好爬。首先引入mongoose,然后使用Schema的構(gòu)造方法新建一個(gè)Schema的實(shí)例甥啄,在構(gòu)造函數(shù)的參數(shù)對(duì)象中定義屬性存炮。

//Require Mongoose
var mongoose = require('mongoose');

//Define a schema
var Schema = mongoose.Schema;

var SomeModelSchema = new Schema({
    a_string: String,
    a_date: Date
});

在上面的例子中,我們只有兩個(gè)屬性蜈漓,一個(gè)字符串穆桂,一個(gè)時(shí)間。在本文的下一段我們會(huì)展示其他屬性類(lèi)型融虽,和校驗(yàn)器和其他方法享完。

創(chuàng)建一個(gè)Model

Model是使用mongoose.model()創(chuàng)建自Schema。

// Define schema
var Schema = mongoose.Schema;

var SomeModelSchema = new Schema({
    a_string: String,
    a_date: Date
});

// Compile model from schema
var SomeModel = mongoose.model('SomeModel', SomeModelSchema );

第一個(gè)參數(shù)是MongoDB中的集合的名有额,mongoose將為上面的Model創(chuàng)建一個(gè)名為SomeModel的集合般又。第二個(gè)參數(shù)是你想要用來(lái)創(chuàng)建Model的Schema 。

一旦你創(chuàng)建了Model巍佑,你可以使用他來(lái)進(jìn)行增刪查改茴迁,既可以查詢(xún)?nèi)坑涗洠部梢圆樵?xún)特定的子集句狼。當(dāng)我們創(chuàng)建我們的視圖時(shí)笋熬,我們會(huì)在“使用Model”段講解如何做。

Schema 中屬性的類(lèi)型

Schema 可以有任意數(shù)量的屬性腻菇,每一個(gè)屬性都代表了在MongoDB中的字段胳螟。下面的例子展示了常用的屬性類(lèi)型是如何被定義的。

var schema = new Schema(
{
  name: String,
  binary: Buffer,
  living: Boolean,
  updated: { type: Date, default: Date.now },
  age: { type: Number, min: 18, max: 65, required: true },
  mixed: Schema.Types.Mixed,
  _someId: Schema.Types.ObjectId,
  array: [],
  ofString: [String], // You can also have an array of each of the other types too.
  nested: { stuff: { type: String, lowercase: true, trim: true } }
})

大多數(shù)屬性類(lèi)型的意義是顯而易見(jiàn)的筹吐,除了以下幾項(xiàng):

  • ObjectId:代表在數(shù)據(jù)庫(kù)中的一個(gè)對(duì)象實(shí)體糖耸,比如,書(shū)本對(duì)象可以使用他來(lái)代表他的作者丘薛。實(shí)際上他包含的是對(duì)象的唯一id(_id)嘉竟。我們可以在需要的時(shí)候使用populate()方法獲取某些信息。
  • Mixed:任意schema類(lèi)型。
  • []:數(shù)組對(duì)象舍扰。你可以對(duì)該對(duì)象執(zhí)行JavaScript數(shù)組操作(push, pop, unshift等)倦蚪。上面的實(shí)例展示了,沒(méi)有指定數(shù)組對(duì)象類(lèi)型的數(shù)組边苹,和指定為String的數(shù)組陵且。你可以指定任意類(lèi)型的數(shù)組。

這段代碼也展示來(lái)定義屬性的兩種方法:

  • 屬性名和屬性類(lèi)型作為鍵值對(duì)个束。
  • 屬性名后緊跟一個(gè)對(duì)象來(lái)定義屬性類(lèi)型慕购,以及屬性的其他選項(xiàng)。選項(xiàng)包含以下這些:
    • 默認(rèn)值
    • 內(nèi)置的校驗(yàn)器(min/max)茬底,或者定制的校驗(yàn)函數(shù)沪悲。
    • 屬性是否是必須的。
    • 屬性是否會(huì)自動(dòng)大寫(xiě)阱表,小寫(xiě)或者去除空格(e.g. { type: String, lowercase: true, trim: true })殿如。
      更多有關(guān)選項(xiàng)的信息,請(qǐng)看SchemaTypes的文檔捶枢。
校驗(yàn)器

Mongoose提供來(lái)內(nèi)置的校驗(yàn)器握截,自定義校驗(yàn)器,同步或者異步校驗(yàn)器烂叔。他用來(lái)指定可用的范圍或者值谨胞,以及在校驗(yàn)失敗時(shí)的錯(cuò)誤信息。

內(nèi)置的校驗(yàn)器包括:

  • 所有的類(lèi)型都包含required校驗(yàn)器蒜鸡。這個(gè)校驗(yàn)器是用來(lái)指定在保存時(shí)胯努,屬性是否是必須的。
  • Numbersminmax校驗(yàn)器逢防。
  • Strings類(lèi)型有:
    • enum:指定這個(gè)屬性所能擁有的值的集合叶沛。
    • match: 指定值必須滿(mǎn)足的正則表達(dá)式。
    • maxlengthminlength

下面的樣例略微修改自Mongoose的文檔忘朝,展示來(lái)如何指定校驗(yàn)器的類(lèi)型和錯(cuò)誤信息灰署。

var breakfastSchema = new Schema({
      eggs: {
        type: Number,
        min: [6, 'Too few eggs'],
        max: 12
        required: [true, 'Why no bacon?']
      },
      drink: {
        type: String,
        enum: ['Coffee', 'Tea', 'Water',]
      }
    });

詳細(xì)的校驗(yàn)器說(shuō)明,請(qǐng)看Mongoose的文檔Validation

虛擬屬性

虛擬屬性是你可以get和set的對(duì)象屬性局嘁,但是他們不會(huì)被保存到MongoDB中溉箕。get方法常常被用來(lái)格式化或者合并屬性,set方法常用來(lái)分解單個(gè)屬性并把他們保存在數(shù)據(jù)庫(kù)中的多個(gè)屬性中悦昵。在本例中用first name和last name屬性去構(gòu)造一個(gè)全名肴茄,相對(duì)于每次在使用時(shí)來(lái)構(gòu)造一個(gè)全名更加清晰和簡(jiǎn)單。

備注:我們將使用虛擬屬性為每條記錄的_id屬性和地址定義一個(gè)唯一URL但指。
更多信息請(qǐng)看Virtuals

方法和查詢(xún)助手

schema可以有實(shí)體方法寡痰,靜態(tài)方法和查詢(xún)助手抗楔。實(shí)體方法和靜態(tài)方法是類(lèi)似的,他們之間明顯的不同是拦坠,實(shí)例方法是關(guān)聯(lián)到實(shí)際對(duì)象的连躏,能夠訪問(wèn)當(dāng)前對(duì)象。查詢(xún)助手允許你擴(kuò)展mongoose的查詢(xún)構(gòu)造器API(比如贞滨,你可以添加“byName”查詢(xún)方法去擴(kuò)展find(), findOne() 和 findById())反粥。

Model的使用

一旦你創(chuàng)建創(chuàng)建了schema,你就可以使用他來(lái)創(chuàng)建Model疲迂。Model代表了數(shù)據(jù)庫(kù)中Document的Collection,而一個(gè)Model的實(shí)體代表了一個(gè)你可以存取的單一對(duì)象莫湘。
下面我們提供一個(gè)概述尤蒿,詳情請(qǐng)看Models

創(chuàng)建和更改document

你可以通過(guò)創(chuàng)建一個(gè)Model實(shí)體并調(diào)用save()方法去保存一條記錄幅垮。下面的例子假設(shè)SomeModel是通過(guò)schema創(chuàng)建的某個(gè)對(duì)象(只有一個(gè)“name”屬性)腰池。

// Create an instance of model SomeModel
var awesome_instance = new SomeModel({ name: 'awesome' });

// Save the new model instance, passing a callback
awesome_instance.save(function (err) {
  if (err) return handleError(err);
  // saved!
});

注意記錄的創(chuàng)建(以及更新,刪除忙芒,查詢(xún))是異步操作示弓,你需要傳遞一個(gè)回調(diào)函數(shù),當(dāng)操作完成時(shí)會(huì)執(zhí)行呵萨。我們遵從錯(cuò)誤優(yōu)先的慣例奏属,所以回調(diào)函數(shù)的第一個(gè)參數(shù)為錯(cuò)誤信息,如果有的話潮峦。如果操作會(huì)返回結(jié)果囱皿,他將被作為第二個(gè)參數(shù)。

你也可以使用create()方法忱嘹,在你定義對(duì)象的同時(shí)保存他嘱腥。回調(diào)函數(shù)將返回錯(cuò)誤信息作為第一個(gè)參數(shù)拘悦,創(chuàng)建的實(shí)體作為第二個(gè)參數(shù)齿兔。

SomeModel.create({ name: 'also_awesome' }, function (err, awesome_instance) {
  if (err) return handleError(err);
  // saved!
});

每一個(gè)Model都有一個(gè)相關(guān)的連接對(duì)象(當(dāng)你使用model()方法時(shí),會(huì)使用默認(rèn)方法)础米,你可以創(chuàng)建一個(gè)新的連接分苇,并調(diào)用他的model()方法,用以在不同的數(shù)據(jù)庫(kù)中創(chuàng)建記錄椭盏。

你可以使用點(diǎn)語(yǔ)法去訪問(wèn)對(duì)象屬性组砚,更改屬性值。你必須使用save()或update()將變更保存到數(shù)據(jù)庫(kù)中掏颊。

// Access model field values using dot notation
console.log(awesome_instance.name); //should log 'also_awesome'

// Change record by modifying the fields, then calling save().
awesome_instance.name="New cool name";
awesome_instance.save(function (err) {
   if (err) return handleError(err); // saved!
   });
搜索數(shù)據(jù)

你可以通過(guò)查詢(xún)方法去檢索數(shù)據(jù)記錄糟红,并用JSON對(duì)象來(lái)指定查詢(xún)條件艾帐。下面的代碼展示了如何查詢(xún)所有參加網(wǎng)球運(yùn)動(dòng)的運(yùn)動(dòng)員,并只返回姓名和年齡盆偿。這里我們只匹配了運(yùn)動(dòng)這一個(gè)屬性柒爸,但是你們可以指定更多的檢索條件,如一個(gè)正則表達(dá)式事扭,或者不要任何條件捎稚,返回所有數(shù)據(jù)。

var Athlete = mongoose.model('Athlete', yourSchema);

// find all athletes who play tennis, selecting the 'name' and 'age' fields
Athlete.find({ 'sport': 'Tennis' }, 'name age', function (err, athletes) {
  if (err) return handleError(err);
  // 'athletes' contains the list of athletes that match the criteria.
})

如果你向上面一樣指定了回調(diào)方法求橄,查詢(xún)會(huì)馬上執(zhí)行今野,而回調(diào)方法會(huì)在查詢(xún)完成后執(zhí)行。

在mongoose中所有回調(diào)函數(shù)都采用了callback(error, result)的形式罐农。如果在查詢(xún)時(shí)發(fā)生錯(cuò)誤条霜,error中將包含錯(cuò)誤信息,而result將返回null涵亏。如果查詢(xún)成功error是null宰睡,而result中包含查詢(xún)的結(jié)果。

如果你沒(méi)有傳遞回調(diào)方法气筋,程序?qū)⒎祷匾粋€(gè)Query對(duì)象拆内。你可以使用這個(gè)query對(duì)象去組建你的查詢(xún),之后調(diào)用exec()方法執(zhí)行他宠默,并傳入回調(diào)方法麸恍。

// find all athletes that play tennis
var query = Athlete.find({ 'sport': 'Tennis' });

// selecting the 'name' and 'age' fields
query.select('name age');

// limit our results to 5 items
query.limit(5);

// sort by age
query.sort({ age: -1 });

// execute the query at a later time
query.exec(function (err, athletes) {
  if (err) return handleError(err);
  // athletes contains an ordered list of 5 athletes who play Tennis
})

上面的代碼中,我們?cè)趂ind中指定了查詢(xún)條件搀矫。我們也可以使用where()方法或南,他能夠使用(.)點(diǎn)語(yǔ)法將所有查詢(xún)條件連接起來(lái),而不用分別指定艾君。下面的代碼等同于上面的代碼采够,但是我們添加了一個(gè)age查詢(xún)條件。

Athlete.
  find().
  where('sport').equals('Tennis').
  where('age').gt(17).lt(50).  //Additional where query
  limit(5).
  sort({ age: -1 }).
  select('name age').
  exec(callback); // where callback is the name of our callback function.

find()方法會(huì)查詢(xún)所有匹配的記錄冰垄,但是通常我們只需要其中的一條蹬癌。下面的方法用以查詢(xún)一條記錄:

提示:也有count()方法逝薪,獲取指定條件的記錄數(shù)。常常用于蝴罪,你只想要知道數(shù)目而不是實(shí)際的記錄時(shí)董济。

查詢(xún)中你還可以作很多,詳情請(qǐng)看:Queries要门。

處理相關(guān)的對(duì)象 -----熱門(mén)

你可以使用ObjectId 屬性類(lèi)型創(chuàng)建一個(gè)索引連接兩個(gè)對(duì)象虏肾,或者使用ObjectId 的數(shù)組去連接多個(gè)對(duì)象廓啊。這個(gè)屬性存儲(chǔ)著model的id。如果你需要關(guān)聯(lián)對(duì)象的實(shí)際內(nèi)容封豪,你可以使用populate()方法去查詢(xún)并替換id為真實(shí)數(shù)據(jù)谴轮。
例如,一下的schema定義了作者和故事吹埠。每個(gè)作者有多個(gè)故事第步,我們將使用ObjectId 數(shù)組來(lái)表示他們。一個(gè)故事只有一個(gè)作者缘琅。"ref"屬性(高亮加粗顯示的粘都,makedown)告訴schema 連接哪個(gè)model。

var mongoose = require('mongoose')
  , Schema = mongoose.Schema

var authorSchema = Schema({
  name    : String,
  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});

var storySchema = Schema({
  author : { type: Schema.Types.ObjectId, ref: 'Author' },
  title    : String,
});

var Story  = mongoose.model('Story', storySchema);
var Author = mongoose.model('Author', authorSchema);

我們可以使用_id值去保存關(guān)聯(lián)對(duì)象的索引刷袍。下面我們創(chuàng)建一個(gè)author驯杜,之后是一個(gè)book對(duì)象,并關(guān)聯(lián)author對(duì)象到author屬性做个。

var bob = new Author({ name: 'Bob Smith' });

bob.save(function (err) {
  if (err) return handleError(err);

  //Bob now exists, so lets create a story
  var story = new Story({
    title: "Bob goes sledding",
    author: bob._id    // assign the _id from the our author Bob. This ID is created by default!
  });

  story.save(function (err) {
    if (err) return handleError(err);
    // Bob now has his story
  });
});

我們的story對(duì)象依靠id獲得了author的索引。為了獲得詳細(xì)的author信息我們使用populate()方法滚局。如下:

Story
.findOne({ title: 'Bob goes sledding' })
.populate('author') //This populates the author id with actual author information!
.exec(function (err, story) {
  if (err) return handleError(err);
  console.log('The author is %s', story.author.name);
  // prints "The author is Bob Smith"
});

血條耗盡居暖。。藤肢。太闺。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市嘁圈,隨后出現(xiàn)的幾起案子省骂,更是在濱河造成了極大的恐慌,老刑警劉巖最住,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钞澳,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡涨缚,警方通過(guò)查閱死者的電腦和手機(jī)轧粟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)脓魏,“玉大人兰吟,你說(shuō)我怎么就攤上這事∶瑁” “怎么了混蔼?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)珊燎。 經(jīng)常有香客問(wèn)我惭嚣,道長(zhǎng)遵湖,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任料按,我火速辦了婚禮奄侠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘载矿。我一直安慰自己垄潮,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布闷盔。 她就那樣靜靜地躺著弯洗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪逢勾。 梳的紋絲不亂的頭發(fā)上牡整,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音溺拱,去河邊找鬼逃贝。 笑死,一個(gè)胖子當(dāng)著我的面吹牛迫摔,可吹牛的內(nèi)容都是我干的沐扳。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼句占,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼沪摄!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起纱烘,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤杨拐,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后擂啥,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體哄陶,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年哺壶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了奕筐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡变骡,死狀恐怖离赫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情塌碌,我是刑警寧澤渊胸,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站台妆,受9級(jí)特大地震影響翎猛,放射性物質(zhì)發(fā)生泄漏胖翰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一切厘、第九天 我趴在偏房一處隱蔽的房頂上張望萨咳。 院中可真熱鬧,春花似錦疫稿、人聲如沸培他。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)舀凛。三九已至,卻和暖如春途蒋,著一層夾襖步出監(jiān)牢的瞬間猛遍,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工号坡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留懊烤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓宽堆,卻偏偏與公主長(zhǎng)得像腌紧,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子日麸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容