数据文档(Data Document)

示例

一个数据文件是数据库的数据组装,表现为一个JSON文件或一个Java嵌套的Map/List。

下面是一个数据文档实例和定义它的记录的示例。此例选自基于Moqui和Mantle的HiveMind PM项目。此文档是一个project,project是WorkEffort的一种。

{
    "_index": "hivemind",
    "_type": "HmProject",
    "_id": "HM",
    "_timestamp": "2013-12-27T00:46:07",
    "WorkEffort": 
    {
        "workEffortId": "HM",
        "name": "HiveMind PM Build Out",
        "workEffortTypeEnumId": "WetProject"
    },
    "StatusItem": { "status": "In Progress" },
    "WorkEffortType": { "type": "Project" },
    "Party": [
          {
          "Person": { "firstName": "John", "lastName": "Doe" },
          "RoleType": { "role": "Person - Manager" },
          "partyId": "EX_JOHN_DOE"
          },
          {
          "Person": { "firstName": "Joe", "lastName": "Developer" },
          "RoleType": { "role": "Person - Worker" },
          "partyId": "ORG_BIZI_JD"
          }
    ]
}

下面是定义此数据文档的数据库记录,格式是EntityFacade XML文件中的记录的格式:

<xml>
    <moqui.entity.document.DataDocument dataDocumentId="HmProject" indexName="hivemind" documentName="Project" primaryEntityName="mantle.work.effort.WorkEffort" documentTitle="${name}"/>

    <moqui.entity.document.DataDocumentField dataDocumentId="HmProject" fieldPath="workEffortId"/>

    <moqui.entity.document.DataDocumentField dataDocumentId="HmProject"  fieldPath="workEffortName" fieldNameAlias="name"/>

    <!-- this is aliased so we can have a condition on it -->

    <moqui.entity.document.DataDocumentField dataDocumentId="HmProject"  fieldPath="workEffortTypeEnumId"/>

    <moqui.entity.document.DataDocumentField dataDocumentId="HmProject"  fieldPath="WorkEffort#moqui.basic.StatusItem:description"
    fieldNameAlias="status"/>

    <moqui.entity.document.DataDocumentField dataDocumentId="HmProject" fieldPath="mantle.work.effort.WorkEffortParty:partyId"/>

    <moqui.entity.document.DataDocumentField dataDocumentId="HmProject" fieldPath="mantle.work.effort.WorkEffortParty:mantle.party.RoleType:description"
    fieldNameAlias="role"/>

    <moqui.entity.document.DataDocumentRelAlias dataDocumentId="HmProject" relationshipName="mantle.work.effort.WorkEffort" documentAlias="WorkEffort"/>

    <moqui.entity.document.DataDocumentRelAlias dataDocumentId="HmProject" relationshipName="WorkEffort#moqui.basic.StatusItem"
    documentAlias="StatusItem"/>

    <moqui.entity.document.DataDocumentRelAlias dataDocumentId="HmProject" relationshipName="mantle.work.effort.WorkEffortParty" documentAlias="Party"/>

    <moqui.entity.document.DataDocumentRelAlias dataDocumentId="HmProject"  relationshipName="mantle.party.RoleType" documentAlias="RoleType"/>

    <moqui.entity.document.DataDocumentCondition dataDocumentId="HmProject"  fieldNameAlias="workEffortTypeEnumId" fieldValue="WetProject"/>

    <moqui.entity.document.DataDocumentLink dataDocumentId="HmProject"  label="Edit Project"  linkUrl="/apps/hm/Project/EditProject?workEffortId=${workEffortId}"/>
</xml>

JSON对象

数据文档实例的顶层对象(JSON术语,在Java中是Map)有3个定义文档的字段:

  • _index: 文档所处的索引,来自文档定义中的 DataDocument.indexName 字段
  • _type: 索引中文档的类型,Moqui框架用作DataDocument定义的ID,来自 DataDocument.dataDocumentId 字段
  • _id: 特定数据文档实例的ID,基于DataDocument.primaryEntityName字段中指定的主实体的主键。

顶层也包含一个 _timestamp 字段,有文档被生成时的日期和时间

这4个字段这样命名,易于ElasticSearch对其进行索引,ElasticSearch是基于数据文档特性的数据搜索特性使用的工具。这些字段、数据文档除了仅仅搜索外,大体上还对通知、集成和多种事情有用。

定义

数据文档定义由这些记录组成:

  • DataDocument: 主记录,由dataDocumentId标识,包含索引名称、(为显示目的的)文档名称
    • primaryEntityName: 文档的主实体,其他文档字段实体与其关联,其他纯字段名属于它
    • documentTitle: 为显示目的,特别是在搜索结果中。注意 documentTitle 值由一个来自数据文档的摊平了的Map扩展,所以扩展后的字段名必须匹配文档的字段名(或别名)
  • DataDocumentField: 每条记录为文档指定一个字段
    • fieldPath: 字段名,可选的前面会有冒号分隔的从主视图到字段所在实体的关系名列表
    • fieldNameAlias: 可选地为字段指定一个名字,以用在文档中,和字段所属的实体上的字段名不一样。文档中的字段名必须在整个文档中唯一,而不仅仅是在此字段所属实体中唯一。不管是实体字段名还是用的别名。理由是:这是用在为文档从数据库获取数据的查询中的别名,并有助于参数搜索。
  • DataDocumentRelAlias: 使用这些记录,通过为fieldPath字段中的关系和primaryEntityName指定别名来产出一个更清晰的文档。
  • DataDocumentCondition: 这些记录约束从数据库为文档获取数据的查询。在上面的例子中,这被用来约束查询只获取有WetProject类型的WorkEffort记录,这样它只包括项目。
  • DataDocumentLink: 在搜索结果和其他用户、系统接口中,它可用于提供关于文档、特别是其中的主实体更多信息的连接。使用这些记录来指定这些链接。注意 linkUrl 的值被一个来自数据文档的摊平了的Map扩展,所以被扩展字段的名字必须匹配文档字段名(或别名)。

在示例文档的顶层对象中,有一个文档中主实体WorkEffort对象。在文档中总会有一个像这样的对象,它的名字是主实体的名字。如果DataDocumentRelAlias记录中没有它的别名,它将是DataDocument.primaryEntityName字段的字面值,这就是为什么在这份文档中对象的名字是 WorkEffort 而不是 mantle.work.effort.WorkEffort。

所有的fieldPath为纯字段名(没有冒号分隔的关系前缀)的 DataDocumentField 记录,映射到主实体上的字段,并且在文档中将被包含在主实体对象中。

所有的带冒号分隔的关系前缀的文档字段将导致顶层文档对象(Map)中的其他条目,key为关系名或者(如果配置了)关系名的别名。如果是一个多对一关系,条目的值将是一个对象/Map;如果是对多关系,那么是一个对象数组(Java中是Map列表)。

fieldPath中有多个冒号分隔的关系名时,应用同样的模式。对象/Map条目将按需嵌套以遵循特定字段的路径。上面HmProject文档中的一个例子是"mantle.work.effort.WorkEffortParty:mantle.party.RoleType:description"fieldPath值。注意那两个关系名是不包含包名的别名,字段别名化为role,而不是description。结果是JSON文档的这部分:

{ "Party": [ { "RoleType": { "role": "Person - Manager" } } ] }

JSON的语法,对象(Map)是大括号({}),数组是中括号([])。所以上面是一个有Party的顶层对象,值是一个内有一个对象的数组,该对象有一个RoleType条目,值是一个有单个条目(键是role,值是来自RoleType.description实体字段)的对象。description字段别名化为role的原因如上面DataDocumentField.fieldNameAlias字段的描述所说:数据文档中的每个字段必须在整个文档中有一个唯一的名字。

生成

有一些方法从数据库中的数据生成数据文档。最有用的方法是下面描述的DataFeed,你也能通过一个API来获取它,像这样:

List<Map> docMapList = ec.entity.getDataDocuments(dataDocumentId, condition, fromUpdateStamp, thruUpdatedStamp)

返回的列表中每个Map表示一个数据文档。condition, fromUpdatedStampthruUpdatedStamp参数可以为null,但是如果指定了,会用作查询数据库时的额外的约束。condition应当为文档中的字段使用字段别名。要查看文档的任一部分是否在某个时间范围内有变化,UpdatedStamp参数被用来查找自动添加的lastUpdatedStamp字段在from/thru范围中的记录。

数据文档的Map和上面示例JSON文档是一样的结构。ElasticSearchAPI支持这种Map形式的文档,但在某些场合中,你会想它是一个JSON字符串。要从Map创建一个JSON字符串,在Groovy中像这样用一个简单的语句:

String docString = groovy.json.JsonOutput.toJson(docMap)

如果你想要一个JSON字符串的更友好的可读的版本,这么做:

String prettyDocString = groovy.json.JsonOutput.prettyPrint(docString)

反过来从JSON字符串到Map,用一条像这样的语句:

Map docMap = (Map) new groovy.json.JsonSlurper().parseText(docString)

查询

一个动态视图实体可以基于一个数据文档定义被自动创建,以在联结进来的实体和别名化的字段上运行查询。要这么做,只要使用一个有这个模式的实体名: DataDocument.${dataDocumentId}

这是保持dataDocumentId值简单(字母、数字、下划线;驼峰风格或下划线分隔)的一个理由。例如,在Groovy中:

EntityList productList = ec.entity.find("DataDocument.MantleProduct").list()

这将使用一个从MantleProduct数据文档(来自mantle-udm)生成的动态视图实体来找到所有记录。动态视图实体将为别名化字段联结进所有需要的实体。

results matching ""

    No results matching ""