實時開發框架Meteor API解讀系列 Collection --01

寫在前面的話

  1. 本篇博客主要講 Collection,由於該部分比較長,會用兩到三篇博客的內容描述.其實這個部分東西不好寫博客,因爲涉及到的都是一些操作語句,這個和mongodb的api有關
  2. 使用的meteor版本爲0.8.0
  3. 老話重提 ,儘量以官方文檔爲主
  4. 本篇博客有不正確的地方在所難免,如有發現望指出。
  5. 本篇博客地址:http://blog.csdn.net/a6383277/article/details/23656929 轉載請註明出處,謝謝
  6. 編程環境:ubuntu (涉及到的shell,代碼等)

Collections

Collctions是meteor中的比較重要的部分,Meteor把數據存儲到Collection中。 Collections對象的函數主要是對數據集合的CURD等操作。如何你對NoSQL有一定的瞭解的話,那麼對這個對象應該會比較熟悉,它的操作與 NoSQL語句類似。 在Meteor中,現在主要是使用Mongodb,在官方文檔中,開發者表示會支持其他的數據庫,不過那是在將來了。

構造函數 new Meteor.Collection(name, [options]) @Anywhere

如果你要聲明一個數據集合Collection(類似於sql中的表的概念),那麼就用上面的構造函數了。先看下它的參數:

name

數據集的名字,String類型。在Mongodb中就有一個與之對應的Collection了。如果這個name爲null,那麼只是生成一個非託管的(臨時的數據集合)數據集合了。至於是什麼意思的,下文通過代碼來解釋。

options

可選的參數有:
connection.這是個object對象,指定連接的服務器對象.具體可以見上一篇博客DDP subscribe相關的內容.這個時候就是訂閱遠程的數據集了.
如果name爲空,那麼就不能使用這個選項.默認情況都是省略該選項的,表明連接本地數據.
idGeneration: 每條數據_id生成的方案,字符串.有兩個選擇:'STRING'和'MONGO',STRING是一個隨機字符串.而MONGO是一個Mongodb的ObjectID對象.使用過就清楚了.默認是 STRING.
transform:在數據發送之前進行一定的處理.它是個function

因此可以像下面幾種方式使用:
//1.創建一個本地數據集,不會保存到數據庫.也不會進行前後臺同步,更不會多客戶端同步了..
LocalPeople = new Meteor.Collection(null);

//2創建一個數據集,會保存到數據庫.這是最普通的用法.也是最普遍的用法
People = new Meteor.Collection("people") 

//3.創建一個遠程服務器的數據集引用.它不會保存到本地數據庫
var remote = DDP.connect('http://localhost:3010');
RemotePeople = new Meteor.Collection("people",remote)

//4.創建一個數據集指定它的ID生成方式
IDPeople = new Meteor.Collection("idpeople",{'idGeneration':'MONGO'})
//或者
//IDPeople = new Meteor.Collection('idpeople',remote,'MONGO')

//5.使用transform
TransformPeople = new Meteor.Collection('tranpeople',{'transform':function(docs){
    console.log("transform:")
    docs['transform']=true;
    console.log(docs);
    return docs;
}});

具體區別請看源碼中的defineCollection函數輸出。

collection.find(selector, [options])

這個是數據查詢函數。

selector

selector一個查詢條件。 
當它是一個字符串時,

collection.find("string")
等同
collection.find({_id:"string"})

也就是說,如果傳入的是字符串,那麼將被當作數據的_id字段使用。

當它是一個Object對象時,(當爲{}空對象時,查詢所有數據)具體規則可以參考Mongodb的find。這裏不多講,也講不完。具體見http://docs.mongodb.org/manual/tutorial/query-documents/ 和操作符 http://docs.mongodb.org/manual/reference/operator/query/

注意,這個find函數返回的不是一個數據數組,而是一個指向數據集的cursor。具體見下面的Cursor部分。

options

object 。可選的操作。對數據結果的處理選項。

sort:進行數據排序
排序規則
People.find({},{sort:[["age", "asc"], ["name", "desc"]]}) //進行age的升序排列,name的降序排列
或者
People.find({},{sort:{a: 1, b: -1}})
如果什麼都不規定則默認爲 自然語序  1,2,3 或者a,b,c,等

skip number  從開始 跳過多少條數據 返回

limitnumber 限制多少條數據返回。

通過使用skiplimit可以實現數據分頁

fields 返回數據字段限制。


 People.find({}, {fields: {age: 0,name:0}}) 返回數據中不包含age,name字段

 People.find({}, {fields: {firstname: 1}})返回數據中'只'包含firstname字段

 注意0表示 排除,1表示 包含。 這兩者不能同時使用。
 這樣使用是錯誤 的:
 People.find({}, {fields: {firstname: 1age: 0}})
 但是有一個例外,那就是_id字段。對於_id字段可以同時使用10.因爲就算沒有使用_id:1,_id字段也是默認返回的。如果不想要_id可以使用如下:
 People.find({}, {fields: {firstname: 1_id: 0}}) 

reactiveboolean 設置返回的數據是不是活性數據源。默認值是true
 People.find({}, {reactive:false})
 如果是活性數據源,那麼引用它的TemplateTemplate對象 一旦結果集發生改變也會跟着改變。
 非活性數據源則不會帶來Template的影響。具體請見Session博客那一章。

 transform:重寫(如果在new Meteor.Collection('xxx',{transform:function(doc){..}})定義過的話)或者新增對於返回前 數據的修改等操作。

在當前代碼裏面,不展示關於remote的使用,我會註釋掉相關,代碼,如果你想使用,請把上篇博客的DDP的main-server跑在3010端口,在取消代碼裏面的註釋即可。在下載代碼包裏,我會包含這個兩個。shell是:

cd main-server
meteor run -p 3010

新開一個終端

cd deputy-server
meteor

deputy-server 結構如下:

- 根目錄
|-Collection.js
-- client 文件夾
  |-client.js
  |-index.html
-- server 文件夾
  |-main.js

Collection.js

//var remote =  DDP.connect("http://localhost:3010");//鏈接遠程服務器
//People  =  new Meteor.Collection('people',remote)

//創建一個本地(臨時)數據集,不會保存到數據庫.
LocalPeople = new Meteor.Collection(null);

//創建一個數據集,會保存到數據庫.這是最普通的用法.也是最普遍的用法
People = new Meteor.Collection("people") 

//創建一個遠程服務器的數據集引用.它不會保存到本地數據庫
//var remote = DDP.connect('http://localhost:3010');
//RemotePeople = new Meteor.Collection("people",remote)

//創建一個數據集指定它的ID生成方式
IDPeople = new Meteor.Collection("idpeople",{'idGeneration':'MONGO'})
//或者
//IDPeople = new Meteor.Collection('idpeople',remote,'MONGO')

//5.使用transform
TransformPeople = new Meteor.Collection('tranpeople',{'transform':function(docs){
    //console.log("transform:==============開始")
    docs['transform']=true;
    //console.log(docs);
    //console.log("transform:==============結束")
    return docs;
}});

client.js 
注意所有的打印都在瀏覽器控制檯

//不同定義的Collection
function defineCollection(){
    console.log("================================defineCollection");
    console.log("RemotePeople findOne:");
    console.log(RemotePeople.findOne());
    console.log("IDPeople findOne:");
    console.log(IDPeople.findOne());
    console.log("People findOne:");
    console.log(People.findOne());
    console.log("LocalPeople findOne:");
    console.log(LocalPeople.findOne());
    console.log("================================defineCollection");
}

Meteor.setTimeout(defineCollection,5000);

function show(object){
    console.log(JSON.stringify(object))
}
//find函數
function find(){
    console.log("原始數據:")
    var oriResult = People.find({}).fetch()
    show(oriResult);
    console.log("sort:");
    var sortResult = People.find({},{sort:{age:1}}).fetch(); //結果集以age升序
    show(sortResult)
    console.log("fields : 只顯示name字段(默認情況下會顯示_id字段)");
    var fieldsResult1 = People.find({},{fields:{name:1}}).fetch(); 
    show(fieldsResult1)
    console.log("fields : 只顯示name字段,不顯示_id字段");
    var fieldsResult2 = People.find({},{fields:{name:1,_id:0}}).fetch(); 
    show(fieldsResult2)
    console.log("fields : 隱藏phone字段");
    var fieldsResult3 = People.find({},{fields:{phone:0}}).fetch(); 
    show(fieldsResult3)

    console.log("skip,limit : 跳過兩條數據,然後顯示2條數據");
    var skipResult2 = People.find({},{skip:2,limit:2}).fetch(); 
    show(skipResult2)

    console.log("綜合應用 : 以age升序,跳過兩條數據,然後顯示2條數據,隱藏phone字段");
    var result = People.find({},{skip:2,limit:2,fields:{phone:0},sort:{age:1}}).fetch(); 
    show(result)

    console.log("在上一個結果綜合應用上所有age + 20")
    var result2 = People.find({},{skip:2,limit:2,fields:{phone:0},sort:{age:1},transform:function(doc){
            doc.age = doc.age+20
            return doc;
        }}).fetch(); 
    show(result2)
}

Meteor.setTimeout(find,10000);

//活性數據源
Template.relative.people = function(){
    return  People.find({}).fetch(); 
}
//非活性數據源
Template.noRelative.people = function(){
    return  People.find({},{reactive:false}).fetch(); 
}

function changeDate(){
    People.insert({age:1000,name:"ChageDate"})
}
//20秒後 改變數據源 發現 沒有reactive:false的 改變了,有reactive:false的部分沒有改變 
//(注意這裏需要刷新一次頁面後才能看到效果,因爲本地的數據還沒有從服務器拿過來就在頁面上顯示了,
    //這是頁面是無數據的,然後服務器數據拉取過來後,數據變化了,前一個是活性數據源所以馬上就顯示了,
    //後一個非活性數據源,就不會顯示數據,所以需要在頁面要等數據緩存下來後刷新一次後,在插入數據才能看到效果
    //其實,第一次數據顯示不出來 也是設置了非活性數據選項的原因)
Meteor.setTimeout(changeDate,15000);

index.html

<body>
    relative====================<br>
    {{> relative}}
    <br>======================================<br>
    no relative====================<br>
    {{> noRelative}}
</body>
<Template name="relative">
    {{#each people}}
        {{name}}-{{age}}-{{address}}<br>
    {{/each}}
</Template>
<Template name="noRelative">
    {{#each people}}
        {{name}}-{{age}}-{{address}}<br>
    {{/each}}
</Template>

main.js

Meteor.startup(function(){
    People.remove({});
    //這裏的People使用的就是collections.js中定義的數據集操作對象
    var peoples = [
        {name:"小A",address:"長沙",phone:"111",age:2},
        {name:"小B",address:"常德",phone:"222",age:4},
        {name:"小C",address:"衡陽",phone:"333",age:3},
        {name:"小D",address:"衡南",phone:"444",age:1},
        {name:"小E",address:"株洲",phone:"555",age:10}
    ];
    for (var i = 0; i < peoples.length; i++)
        People.insert(peoples[i]);


    //LocalPeople初始化一條數據
    LocalPeople.insert({name:"LocalPeople"}); //無法在客戶端找到它,因爲它是非同步的 

    IDPeople.insert({name:"IDPeople"})

    TransformPeople.insert({name:"TransformPeople"})
});

第一部分到此結束

代碼下載去我的github:github.com/huyinghuan/Lesson 的Meteor/API-007目錄下。 
或者CSDN下載:

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