2012-06-18 35 views
1

我正在研究一個文檔結構,它可以在保持可重建結構的同時輕鬆搜索。我的意思是,文檔本身包含CMS所需的信息,用於構建更新文檔所需的表單。搜索和CMS使用的最有效的JSON/mongodb文檔結構是什麼?

關鍵在於文檔的最終結構永遠不會被知道,因爲它將通過CMS進行構建/修改。

目標是確保前端內容方法可以快速搜索,同時使CMS能夠重建內容以便管理。我毫不猶豫地讓CMS的管理區域工作更加努力,速度並不那麼重要。

這是一個基本的例子

這是一個非常簡短的文檔,但它可以說明我的觀點。該文檔相對容易查詢,但沒有關於CMS如何顯示它的結構信息。

{ 
"name" : "Page Name", 
"title" : "Page Title", 
"description" : "Page Description", 
"page_heading" : "New Heading", 
"content_body" : "<p>New Content</p>", 
"slideshow" : 
    [ 

     { 
     "image_title" : "Vacation Hawaii", 
     "image_file" : "hawaii100.jpg" 
     }, 
     { 
     "image_title" : "Vacation Spain", 
     "image_file" : "Spain200.jpg" 
     }, 
    ] 
} 

這裏是縮寫結構數據

這種方法的問題是,查詢變得更困難的例子。

> db.posts.find({ page_heading.value : "example" }) 

-

{ 

"name" : "Page Name", 
"title" : "Page Title", 
"description" : "Page Description", 

"page_heading" : 
{ 

    "value" : "This is the page heading", 
    "type" : "string", 

}, 
"content_body" : 
{ 

    "value" : "<p>HTML Content</p>", 
    "type" : "html_textarea", 

}, 
"slideshow" : 
{ 
    "type" : 
    { 
     "image_title" : "string", 
     "image_file" : "file" 
    }, 
    "value" : 
    [ 
     { 
      "image_title" : "Vacation Hawaii", 
      "image_file" : "hawaii100.jpg" 
     }, 
     { 
      "image_title" : "Vacation Spain", 
      "image_file" : "Spain200.jpg" 
     }, 
    ] 
} 
} 

另類視角

有單獨的文件,一個用於數據,一個用於模板,似乎是一個可行的解決方案,但增加了物流的複雜性位。

內容文件鏈接到模板

{ 
"name" : "Page Name", 
"title" : "Page Title", 
"description" : "Page Description", 
"template" : "document_id", 
"page_heading" : "New Heading", 
"content_body" : "<p>New Content</p>", 
"slideshow" : 
    [ 

    { 
     "image_title" : "Vacation Hawaii", 
     "image_file" : "hawaii100.jpg" 
    }, 
    { 
     "image_title" : "Vacation Spain", 
     "image_file" : "Spain200.jpg" 
    }, 
    ] 

} 

模板文檔

{ 
"parent" : "document_id", 
"page_heading" : 
{ 

    "type" : "string", 
    "required" : true 

}, 
"content_body" : 
{ 

    "type" : "html_textarea", 
    "required" : true 


}, 
"slideshow" : 
{ 
    "type" : 
    { 
     "image_title" : "string", 
     "image_file" : "file" 
    } 
} 
} 

什麼是最好的方法?

我很可能會把整個事情搞得複雜化,而且在我面前有一個簡單的解決方案。

+0

對不起,如果我錯過了你的問題,但定義「最好」。可擴展的?高效?爲什麼搜索查詢在第二種方法中變得「更困難」? CMS的目標受衆是什麼 - 您或整個世界? –

+0

謝謝您對此的意見。我認爲我通過在查詢速度方面說高效來定義最好,但是在處理文檔方面的可擴展性和總體效率也很重要。我只能索引已知字段,因爲大多數字段不會被知道,似乎查詢會更快,沒有嵌入式文檔,因爲結構中混合了數據。 CMS將被公共使用。 – sterling

+0

由於字段是不可知的,聽起來你可以使用鏈接到其他文檔ID的全文索引 - 你如何觸發這個索引的更新將是你的下一個挑戰。 MongoDB不適用於全面的全文搜索-http://www.mongodb。org/display/DOCS/Full + Text + Search + in + Mongo#FullTextSearchinMongo-ComparisontoFullTextSearchEngines –

回答

2

偉大的問題,我發現自己搔了搔頭很長一段時間。 我將簡要介紹一下我所做的事情,但總之:是的,請分開這些東西。我已經走得更遠了,但是再一次,我可能有其他一些要求。

請考慮以下事項。

  • Entity可以是從產品到Blogpost(由其角色定義的任何東西,實體可以有多個角色)。
  • 一個Entity有很多Facts
  • 一切已知的關於像標題,描述,蛞蝓,英雄圖像,作者的實體等被保存爲Fact該實體。
  • 所有寫操作上單獨Facts和事實的工作。 (換句話說,應用程序的編輯部分只關注事實,因爲事實在任何類型的網頁,我的編輯代碼(如情態動詞實現的當前工作)在任何類型的網頁的工作)
  • Facts可以的任何給定的類型,但該類型必須在FactSchema中定義。 CMS允許在飛行中創建Factschema,從而啓用新的事實類型。
  • 其中一個事實可編輯的方式(這樣說,每個時隙openinghour多個下拉菜單openinghours)可以是在其出現的方式完全不同。所以我需要變壓器的可能性(在寫和讀之間)。現在,這可能不需要你,但是這使我以下內容:
  • Facts從不直接用於顯示(這樣就可以讀取)頁面。相反,當事實處於編輯模式時,它們只會被懶惰地加載。這節省了很多帶寬,因爲很多東西,如歷史記錄,進行中的更改,允許的編輯角色等可能與事實保存在一起
  • 要使facts可用於讀取每個實體有一個.c(用於計算)屬性。創建/更改時,每個fact都將事實名稱保存爲該屬性下的一個鍵(如果已定義,則應用變換器)。
  • 當前渲染方法是,在將對象生成的JSON扔到對象之前,將其展平爲.c一個用於渲染的服務器端模板引擎。 (因此,.c中的所有屬性都成爲包含對象的屬性)

就是這樣。此外,ZERO表示邏輯在這些模型中定義,這是在Mustache/Hogan模板中定義的。 (如果我需要擴展無邏輯模板的可能性,則可以使用兩種混合的JavaScript函數,就顯示邏輯而言)。

搜索可以/應該以事實爲.c定義完成。雖然我通過Elasticsearch來做到這一點。

下面是這3點模式聲明(簡體)(P.S:模式的是Node.js的,但不應該打擾你)

var fact= new Schema(
    { 

     //_id undefined > defaulting to mongoDB objectid instead 

     //factschema is looked-up by name 
    name: { type: String, required: true, index: { unique: false }} 

    //value can be any type, but for a particular instance the type is restricted as set in FactSchema.valueType 
    ,value: {type: {}, required: true} 


    ,createddate : { type: Date, required: true, default: Date.now, select: false } 
} 



var entity= new Schema(
    facts: { type:[require('./fact')], select:false} 
    ,roles: {type: [String], required: true, index: {unique: false}}  
    ,c: {type: {}} //all calculated stuff based on facts 
} 



var factSchema= new Schema({ 
    name: { type: String, required: true, index: { unique: true }} 
    , valueType: { type: {}, required: true} //any type may be defined (simple types but also complex-types which have a ref to their own schema) , fact-instances are checked to adhere to the specified type in pre-save handlers. 
    ,roles: {type: [String], required: true} //roles that are allowed to contain facts based on this factschema 
    ,isMulti: {type: Boolean, required: true } 

    //format to show edit-mode in. 
    ,formFieldType: {type: String, required: true} 

    //ACL-stuff 
    ,directChangeRoles: {type: [String]} //i.e: [super, admin,owner] 
    ,suggestChangeRoles: {type: [String]} //ie: [editor] 
} 

我必須說,這個工程相當不錯。心連心。

+0

謝謝你這個奇妙的詳細答案。事實上,你確實走得更遠一些,但你現在已經讓我思考了不同的方向。你是否也在mongo中存儲事實模式? – sterling

+0

確實,所有內容都在Mongo中定義。至於'factSchema.formFieldType'可能不會從名稱中清楚,這裏定義的名稱用於客戶端查找格式以顯示事實。這不一定只是一個表單字段,但可能是許多形式領域(例如:以'開放時間'爲例),它們一起映射到1個事實。在該客戶端代碼中也提供了將字段映射回Json的代碼。 –

相關問題