1

我正在研究一种可以轻松搜索的文档结构,同时保持可重建的结构。我的意思是文档本身包含 CMS 构建更新文档所需的表单所需的信息。

关键是永远不会知道文档的最终结构,因为它将通过 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"
    }
}   
}

最好的方法是什么?

我很有可能把整个事情复杂化了,而我面前有一个简单的解决方案。

4

1 回答 1

2

很好的问题,我发现自己在很长一段时间内都摸不着头脑。我将简要介绍我所做的事情,但简而言之:是的,请务必将这些内容分开。我已经走得更远了,但话又说回来,我可能还有其他一些要求。

考虑以下。

  • AnEntity可以是从 Product 到 Blogpost 的任何东西(由它的角色定义。一个实体可以有多个角色)。
  • Entity有很多Facts
  • 关于一个实体的所有已知信息,如标题、描述、slug、英雄形象、作者等,都被保存Fact为该实体。
  • 所有的写操作都只对FactsFacts 起作用。(换句话说,应用程序的编辑部分只关心事实,因为事实适用于任何类型的页面,我的编辑代码(当前实现为模态)适用于任何类型的页面)
  • Facts可以是任何给定类型,但该类型必须在FactSchema. CMS 允许Factschema动态创建 s,从而启用新类型的事实。
  • 可以编辑事实的方式(例如,每个开放时间时段具有多个下拉菜单的开放时间)可能在其呈现方式上完全不同。因此我需要变压器的可能性(在写和读之间)。现在,您可能不需要这,但这使我得出以下结论:
  • Facts永远不会直接用于显示(因此阅读)页面。相反,当事实处于编辑模式时,它们只会延迟加载。这节省了很多带宽,因为很多东西,比如历史、正在进行的更改、允许的编辑角色等,都可以与事实一起保存
  • 为了使facts每个实体可供阅读,每个实体都有一个.c(用于计算的)属性。每个fact创建/更改时都以事实名称作为该属性下的键保存(如果已定义,则应用转换器。)
  • 当前的渲染方法是,.c在将生成的 JSON 扔到服务器端模板引擎进行渲染之前,我在对象中展平。(因此,所有属性都.c成为包含对象的属性)

就是这样。此外,在这些模型中定义了零表示逻辑,而是在 Mustache/Hogan 模板中定义。(如果我需要使用无逻辑模板扩展可能的功能,则使用几个混合的 javascript 函数,就表示逻辑而言)。

可以/应该根据 中定义的事实进行搜索.c。虽然我是通过 Elasticsearch 做到这一点的。

这是这 3 个模式声明(简化)(ps:模式在 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]
}

我必须说这很好用。嗯。

于 2012-06-19T16:11:11.947 回答