Dorado 9 : 05. DataPath

  • DataPath可称为数据路径。
  • DataPath是在Dorado的客户端所使用的,用于描述如何提取、挖掘数据的表达式。其作用比较类似于XML中所使用的XPath。
  • DataPath既可以作用在普通的JSON数据上,也可以作用在Dorado所特有的EntityList+Entity数据上。

假设我们现在有一组如下结构的Entit+EntityList数据,其中包含Department和Employee两种实体类型,其中Department支持递归嵌套。下面的说明和示例都将围绕这组数据展开。

[
    {
        id: "D1",
        name: "XX部1",
        departments: [
            {
                id: "D11",
                name: "XX部2",
                employees: [
                    {
                        id: "0001",
                        name: "John",
                        sex: "male",
                        salary: 5000
                    },
                    ...
                ]
            },
            ...
        ]
    },
    ...
]

DataPath的基本语法为:

属性名1(参数1,参数2,..)[逻辑表达式1,逻辑表达式2,..].属性名2(参数1,参数,..2)[逻辑表达式1,逻辑表达式2,..].属性名n..

DataPath中各种特殊符号的说明:

  • ; - 用于分隔多个表达式的分隔符。例如:<code>表达式1;表达式2</code>,最终得到的结果是这两个表达式的结果的简单合集(即可能包含重复元素的合计)。
  • . - 用于分隔不同层级间对象的属性。例如:<code>employee.id</code>表示employee子对象的id属性。
  • * - 用于表示某一层级中所有的对象,一般仅用于表示顶层集合中的对象,且可以省略。例如:<code>*.id</code>表示所有顶层对象的id属性。
  • () - 用于定义一组表达式执行参数,多个参数之间以","分割。目前支持的参数包括:
    • repeat - 重复的执行当前的表达式片段直到无法找到更多的子对象为止。可简写为"R"。例如:

.employees(repeat)

.employees(R)

    • 表示所有employees属性中的对象的集合,这些对象会被提取出来被平行的放置到一个返回的数组中。
    • leaf - 重复的执行当前的表达式片段找出所有的叶子对象。可简写为"L"。
    • 数字 - 表示仅返回找到的前n个对象。
  • @ - 用于逻辑表达式中,表示当前正被过滤的数据对象。
  • [] - 用于定义一组逻辑表达式以对数据进行过滤,其中如果要定义多个逻辑表达式可以以","进行区隔。例如:

employees[@.get("sex")=="male"]

  • 表示筛选出性别为男性的员工。
  • # - DataPath中支持一些以#开头的特殊的逻辑表达式,用于声明对Entity对象的过滤方式。具有如下几种取值:
    • #current - 表示集合中的当前Entity对象。例如:

employees[#current]

    • 表示返回employees集合中的当前Employee对象。
    • #dirty - 表示集合中所有在客户端被改变过的(包含被删除的)Entity对象。
    • #new - 表示集合中所有在客户端新增的Entity对象。
    • #modified - 表示集合中所有在客户端被修改过的Entity对象。
    • #deleted - 表示集合中所有在客户端被标记为已删除的Entity对象。
    • # - #current的简式。例如:

#employees

employees[#current]

    • 具有完全相同的语义。
    • ! - 表示后面是一段自定义的数据路径片段。例如:

!CURRENT_NODE.children

    • 中的CURRENT_NODE就是一个自定义片段。见jsdoc中关于dorado.DataPath.registerInterceptor()方法的说明。

更多的示例:

  • null(即空) - 相当于直接返回被查询的数据。表示顶层集合中所有的(不包含被删除的)Department。
  • * - 同上。
  • # - 表示顶层集合中的当前Department。
  • [#current] - 同上。
  • [#dirty] - 表示顶层集合中所有在客户端被改变过的(包含被删除的)Department。
  • #.employees - 表示顶层集合中当前Department中所有的Employee。
  • #.#employees - 表示顶层集合中当前Department中的当前Employee。
  • #.#departments.#employees - 表示顶层集合中当前Department中的当前Employee。
  • *.departments - 表示所有第二层的Department。
  • .departments - 同上。
  • departments(repeat) - 表示所有Department的集合。注意:示例数据的顶层是一个集合,而在正常情况下是不能利用表达式来获取集合属性的。除非当一个具有repeat或leaf特性的表达式片段被应用于顶层集合时。引擎允许这样的特例,在此种情况下引擎会暂时忽略表达式片段中的属性名。
  • .departments(R) - 表示除顶层Department外所有其它Department的集合。
  • .#departments(R) - 表示除顶层Department外所有其它各层中当前Department的集合。
  • #departments(R) - 表示各层当前Department的集合。
  • #departments(leaf) - 表示最末端的当前Department。即通过不断的尝试获取当前Department中的当前Department,直到最末端那个Department。
  • #departments(L) - 同上。
  • #departments(L).#employees - 表示最末端的当前Department中的当前Employee。此表达式返回的结果是所有匹配Employee组成的数组。
  • .employees(R) - 表示所有employees属性中的对象的集合,即所有的Employee对象。
  • .#employees(R) - 表示所有Department中的当前Employee,将以数组的形式返回这些Employee实体的集合。
  • .employees(R)[@.get("sex")=="male"] - 表示所有Department中的男性Employee,将以数组的形式返回这些Employee实体的集合。
  • .employees(R)[#dirty,@.get("sex")=="male"] - 表示所有Department中的状态为已修改的男性Employee,将以数组的形式返回这些Employee实体的集合。
  • .employees(R)[@.get("salary")>3500 && @.get("sex")=="male"] - 同上。
  • .employees(R)[@.get("salary")>3500, @.get("sex")=="male"] - 表示所有Department中的薪水高于3500的男性Employee,将以数组的形式返回这些Employee实体的集合。
  • .employees(R).id - 表示返回所有Employee对象的id属性值的集合,即所有的Employee对象的id。