Tileset尺寸

作者

托马斯堡

联系方式

联系方式请见: terriscope.fr

作者

塞思 吉尔文

联系方式

在Compass.ie就职

作者

杰罗姆·布伊

最后更新

2018/06/29

版本

1.8

介绍

MapServer中的WMS层可以支持维度,详情请参见 WMS Dimension 。mapcache还支持tileset的维度。

为不同的维度存储单独的平铺缓存有几个实际的用例,例如为不同的空间边界、高程或时间段创建缓存。它还提供了一种基于维度值动态切换 Mapfile 的机制。

mapcache使用维度来:

  • 使用模板结构和 {{dim}} 替换条目,请参见 Template Structure ,参见 磁盘高速缓存Using Multiple SQLite Database FilesSQLite缓存 .

  • 使用自定义架构和 :dim 替换条目,请参见 Custom Schema 在里面 SQLite缓存 .

  • 对WMS源的生成请求:每当缓存丢失时,为tileset指定的任何维度都将转发到其WMS源。

在MapCache中启用维度支持

在配置文件中的 Tileset 水平。每个tileset可以用 <dimensions> 包括一个或多个的部分 <dimension> 元素。

维度属性

为定义了多个属性 <dimension> 元素。

  • name (必需):WMS请求中引用维度的名称(减去 dim_ 中指定的前缀 WMS 1.1.1 Specification

  • default (必需):如果在WMS请求中未显式提供维度,则为该维度的默认值。

  • type (必需):mapcache定义了几种指定维度的方法: valuesregexsqlitepostgresqlelasticsearchtime . 它们将在以下部分中介绍。

  • unit (可选):尺寸单位。此信息仅在getCapabilities响应中使用。

维数类型

mapcache支持几种维度:values、regex、sqlite、postgresql、elasticsearch和time。根据维度值的定义,它们可以分为两组:

  • 第一级维度类型:值和regex。维度值在配置文件中静态指定。

  • 二级维度类型:SQLite, PostgreSQL, Elasticsearch 与 Time。维度值存储在动态后端(SQLite文件、PostgreSQL数据库或 Elasticsearch 索引)中,因此维度值中的更新不涉及服务器重新启动。

一级尺寸

第一级维度在配置文件中定义值。

值维度

值类型维度列出所有可能的维度值。例如,通过WMS或WMTS服务访问时,维度的名称用作查询字符串中的键。 &DIM1=foobarbaz .

如果客户机不提供维度作为键值对,则将使用默认值(在本例中 foobar

<tileset name="LayerName">
    <source>LayerSource</source>
    <cache>sqlite</cache>
    <grid>GoogleMapsCompatible</grid>
    <format>PNG</format>
    <metatile>5 5</metatile>
    <metabuffer>10</metabuffer>
    <dimensions>
        <dimension type="values" name="DIM1" default="foobar">
            <value>foobar</value>
            <value>foobarbaz</value>
            <value>foo</value>
            <value>bar</value>
        </dimension>
    </dimensions>
</tileset>

Regex尺寸

硬编码值列表的另一种选择是使用正则表达式。

下面的示例创建一个mapfile维度,用于将同一个mapcache tileset与不同的mapserver mapfiles一起使用。mapcache不需要知道 Mapfile 的名称,因此可以在启动mapcache之后创建。

当用户通过 MAPFILE=/path/to/mapfile 字符串 /path/to/mapfile 根据提供的(PCRE)正则表达式进行验证。本例中的名称允许由字母数字字符组成,这些字母数字字符由斜杠(/)分隔,并以“.map”([A-ZA-Z0-9./]*.map$)结尾,但如果路径中有两个连续的点(..)则会失败,以防止文件系统遍历。

<dimension type="regex" name="MAPFILE" default="/path/to/mapfile.map">
        <regex>^(?!.*\.\.)[a-zA-Z0-9\./]*\.map$</regex>
</dimension>

二级尺寸

第二级维度将值存储在动态后端、SQLite文件、PostgreSQL数据库或ElasticSearch索引中。这允许在不修改mapcache配置文件的情况下添加新的维度值,否则将需要重新启动服务器。

sqlite维度

在sqlite维度中,维度值存储在sqlite文件中。此外,每个值引用用于查询缓存的内部或子维度值列表。

例如,让我们定义一个“传感器”尺寸,其允许值代表各种地球观测航天器。具有该维度的WMS请求可能包含,例如: ...&dim_sensor=spot&... 在本例中,每个传感器沿着内部“产品”子维度引用多个数据。“传感器”尺寸后端内容的示例如下表所示:

传感器尺寸

产品子维度

地点

spot-img1

地点

spot-img2

phr

phr-img1

phr

phr-img2

phr

phr-img3

WMS请求发生在“传感器”尺寸级别。缓存查询在“产品”子维度级别执行。如果缓存未命中,“product”子维度值用于查询数据源。

查询后端可能会导致返回多个子维度值,每个子维度值都引用不同的分片。组装这些对象的说明见 Tile Assembly Policies 下面部分。

通过指定三个元素来配置sqlite维度:

  • <dbfile> :实现维度的sqlite文件的位置

  • <list_query> :SQL查询返回维度的所有子维度值,例如 spot-img1spot-img2phr-img1phr-img2phr-img3 在“传感器”尺寸示例中。

  • <validate_query> :返回给定维度值的子维度值列表的SQL查询,例如 spot-img1spot-img2 对于 spot “传感器”尺寸示例中的尺寸值。

<!-- "sqlite" dimension

     This example defines a "sensor" dimension whose possible values are
     stored in the /data/sensor.sqlite SQLite file. The default value is
     "phr".

     A WMS request with that dimension may contain, e.g.
     "... &dim_sensor=spot& ..."
-->
<dimension type="sqlite" name="sensor" default="phr">

   <!-- Access Point -->
   <dbfile>/data/sensor.sqlite</dbfile>

   <!-- All-values Query -->
   <list_query>
      SELECT distinct(product) FROM dim
   </list_query>

   <!-- Selected-values Query -->
   <validate_query>
      SELECT product FROM dim
       WHERE sensor=:dim
   </validate_query>

</dimension>

如本例所示 :dim 占位符,查询可以包含模板条目。见 Templating dimension queries 下面部分。

PostgreSQL维度

PostgreSQL维度与SQLite维度非常相似。特别是,上面一节中描述的子维度特性也可用于PostgreSQL维度。它们只在后端实现(PostgreSQL数据库)和配置方式上有所不同。PostgreSQL维度通过指定三个元素进行配置:

  • <connection> :实现维度的PostgreSQL数据库的连接信息,如 PQconnectdb() libpq-c库的功能。

  • <list_query> :SQL查询返回维度的所有子维度值,例如 spot-img1spot-img2phr-img1phr-img2phr-img3 在“传感器”尺寸示例中。

  • <validate_query> :返回给定维度值的子维度值列表的SQL查询,例如 spot-img1spot-img2 对于 spot “传感器”尺寸示例中的尺寸值。

<!-- "postgresql" dimension

     This example defines a "sensor" dimension whose possible values are
     stored in the postgresql://mapcache:mapcache@localhost:5433/mapcache
     PostgreSQL database. The default value is "phr".

     A WMS request with that dimension may contain, e.g.
     "... &dim_sensor=spot& ..."
-->
<dimension type="postgresql" name="sensor" default="phr">

   <!-- Access Point -->
  <connection>
    host=localhost user=mapcache password=mapcache dbname=mapcache port=5433
  </connection>

   <!-- All-values Query -->
  <list_query>SELECT distinct(product) FROM dim</list_query>

   <!-- Selected-values Query -->
  <validate_query>SELECT product FROM dim WHERE sensor=:dim</validate_query>

</dimension>

如本例所示 :dim 占位符,查询可以包含模板条目。见 Templating dimension queries 下面部分。

弹性搜索维度

ElasticSearch维度类似于SQLite或PostgreSQL维度。特别是,上面一节中描述的子维度特性也可用于ElasticSearch维度。ElasticSearch与SQLite和PostgreSQL的主要区别在于,它的查询语言是基于JSON而不是SQL的查询DSL。因此, <list_query><validate_query> 元素应包含用该语言表示的查询。在XML配置中插入JSON数据可能需要将其封装到 <![CDATA[ ... ]]> 元素。

此外,ElasticSearch响应的复杂结构(也用JSON表示)也提出了从查询响应中获取子维度值的提取指令需求。

例如,假设此ElasticSearch查询:

{   "size": 0,
    "aggs": { "distinct_product": { "terms": { "field": "product/keyword" } } },
    "query": { "term": { "sensor": "phr" } }
}

返回此响应:

{   "took": 0,
    "timed_out": false,
    "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 },
    "hits": { "total": 5, "max_score": 0, "hits": [] },
    "aggregations": {
        "distinct_product": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
                { "key": "phr_img1", "doc_count": 1 },
                { "key": "phr_img2", "doc_count": 1 },
                { "key": "phr_img3", "doc_count": 1 }
            ]
        }
    }
}

然后,预期的子维度值为:

[ "phr_img1", "phr_img2", "phr_img3" ]

此列表是通过提取 aggregations 来自外部字典的项,然后 distinct_product 然后 buckets . 最后 key 项目将从每个字典中提取 bucket 名单。提取指令采用类似路径的关键字列表的形式,用于从ElasticSearch提供的JSON响应中提取子维度值:

[ "aggregations", "distinct_product", "buckets", "key" ]

这是通过新的XML元素在mapcache配置文件中指定的,即 <list_response><validate_response> ,分别包含提取说明 <list_query><validate_query> 查询。

ElasticSearch维度通过指定五个元素来定义:

  • <http> :实现维度的ElasticSearch索引的连接信息。此元素包含两个子元素:

    • <url> :ElasticSearch索引的搜索URL

    • <headers> :访问ElasticSearch索引所需的HTTP头。它必须包含标记: <Content-Type>application/json</Content-Type> .

  • <list_query>Query DSL 查询以获取维度的所有子维度值。此查询以JSON格式表示,可能需要在 <![CDATA[ ... ]]> 标签。

  • <validate_query>Query DSL 用于获取给定维度值的子维度值列表的查询。此查询以JSON格式表示,可能需要在 <![CDATA[ ... ]]> 标签。

  • <list_response> :从原始ElasticSearch响应中提取实际子维度值所需的连续关键字列表 <list_query> 查询。

  • <validate_response> :从原始ElasticSearch响应中提取实际子维度值所需的连续关键字列表 <validate_query> 查询。

<!-- "elasticsearch" dimension

     This example defines a "sensor" dimension whose possible values are
     stored in the http://localhost:9200/sensor ElasticSearch index. The
     default value is "phr".

     A WMS request with that dimension may contain, e.g.
     "... &dim_sensor=spot& ..."
-->
<dimension type="elasticsearch" name="sensor" default="phr">

  <!-- Access Point -->
  <http>
    <url>http://localhost:9200/sensor/_search</url>
    <headers>
      <Content-Type>application/json</Content-Type>
    </headers>
  </http>

  <!-- Selected-values Query -->
  <validate_query><![CDATA[
    { "size": 0,
      "aggs": {
        "products": { "terms": { "field": "product.keyword" } }
      },
      "query": { "term": { "sensor": ":dim" } }
    }
  ]]></validate_query>

  <!-- Selected-values Response Extration Instructions -->
  <validate_response><![CDATA[
    [ "aggregations", "products", "buckets", "key" ]
  ]]></validate_response>

  <!-- All-values Query -->
  <list_query><![CDATA[
    { "size": 0,
      "aggs": {
        "products": { "terms": { "field": "product.keyword" } }
      }
    }
  ]]></list_query>

  <!-- All-values Response Extration Instructions -->
  <list_response><![CDATA[
    [ "aggregations", "products", "buckets", "key" ]
  ]]></list_response>
</dimension>

如本例所示 :dim 占位符,查询可以包含模板条目。见 Templating dimension queries 下面部分。

时间维度

mapcache支持包含时间参数的WMT和WMS请求,包括时间戳和时间间隔。见 MS RFC 96: Time Dimension Support in MapCache Tilesets 进一步细节的初步建议。

在mapcache 1.6.1之前,定义时间维度涉及到一个sqlite后端。必须提供两个要素:

  • <dbfile> :实现时间维度的sqlite文件的位置

  • <query> :SQL查询返回给定时间间隔内可用时间戳值的列表。在该查询中,开始时间和结束时间由各自的占位符表示。 :start_timestamp:end_time_stamp . 返回值应为 yyyy-mm-ddThh:mm:ssZ 时间格式,如 RFC 3339 ,但仅限于UTC。

从Mapcache 1.8开始,时间维度的动态后端可以是PostgreSQL数据库或ElasticSearch索引以及sqlite文件。通过设置 time="true" sqlite、postgresql或elasticsearch维度配置中的属性。

不过,mapcache使用隐式的sqlite后端来保持(几乎)向后兼容的时间维度配置。以下部分中的示例突出显示了差异。

用于查询动态后端的时间值用Unix时间表示,即自1970年1月1日(午夜UTC)以来经过的秒数。返回的时间应该是与MapServer兼容的字符串(请参见 WMS Time documentation 详情请参阅。

使用间隔查询后端可能会导致返回多个时间戳值,每个时间戳值都引用不同的分片。组装这些切片的说明见 Tile Assembly Policies 下面部分。

使用默认的sqlite后端配置时间维度

<!-- "time" dimension

     This example defines a "time" dimension whose possible values
     are stored in the /path/to/mapcache-time.sqlite SQLite file. The
     default value is "2010".

     A WMS request with that dimension may contain, e.g.  "...
     &time=1999-08-11T11:03:07Z/2001-09-21T08:17:56Z& ..."
-->
<dimension type="time" name="time" default="2010">
    <dbfile>/path/to/mapcache-time.sqlite</dbfile>
    <query>
         SELECT strftime("%Y-%m-%dT%H:%M:%SZ",ts) FROM time
          WHERE ts &gt;= datetime(:start_timestamp,"unixepoch")
            AND ts &lt;= datetime(:end_timestamp,"unixepoch")
       ORDER BY ts DESC
    </query>

</dimension>
<!-- "time" dimension

     This example defines a "time" dimension whose possible values
     are stored in the /path/to/mapcache-time.sqlite SQLite file. The
     default value is "2010".

     A WMS request with that dimension may contain, e.g.  "...
     &time=1999-08-11T11:03:07Z/2001-09-21T08:17:56Z& ..."
-->
<dimension type="time" name="time" default="2010">
    <dbfile>/path/to/mapcache-time.sqlite</dbfile>
    <validate_query>
         SELECT strftime("%Y-%m-%dT%H:%M:%SZ",ts) FROM time
          WHERE ts &gt;= datetime(:start_timestamp,"unixepoch")
            AND ts &lt;= datetime(:end_timestamp,"unixepoch")
       ORDER BY ts DESC
    </validate_query>
    <list_query>SELECT strftime("%Y-%m-%dT%H:%M:%SZ", ts) FROM time</list_query>
</dimension>

到 MapCache 1.6.1

从上的Mapcache 1.8

使用显式后端配置时间维度

 <!-- "time" dimension, "new-style" definition using a SQLite back-end

      This example defines a "time" dimension whose possible values are
      stored in the /data/times.sqlite SQLite file. The default value is
      "d1".

      A WMS request with that dimension may contain, e.g.
      "... &time=1999-08-11T11:03:07Z/2001-09-21T08:17:56Z& ..."
 -->
 <dimension type="sqlite" name="time" default="d1" time="true">
   <dbfile>/data/times.sqlite</dbfile>
   <list_query>SELECT strftime("%Y-%m-%dT%H:%M:%SZ", ts) FROM timedim</list_query>
   <validate_query>
        SELECT strftime("%Y-%m-%dT%H:%M:%SZ",ts) FROM timedim
         WHERE ts &gt;= datetime(:start_timestamp,"unixepoch")
           AND ts &lt;= datetime(:end_timestamp,"unixepoch")
      ORDER BY ts DESC
   </validate_query>
 </dimension>
 <!-- "time" dimension, "new-style" definition using a PostgreSQL back-end

      This example defines a "time" dimension whose possible values are
      stored in the postgresql://mapcache:mapcache@localhost:5433/time
      PostgreSQL database. The default value is "d1".

      A WMS request with that dimension may contain, e.g.
      "... &time=1999-08-11T11:03:07Z/2001-09-21T08:17:56Z& ..."
 -->
 <dimension type="postgresql" name="time" default="d1" time="true">
   <connection>
     host=localhost user=mapcache password=mapcache dbname=times port=5433
   </connection>
   <list_query>SELECT to_char(ts, 'YYYY-MM-DD"T"HH24:MI:SS"Z"') FROM timedim</list_query>
   <validate_query>
        SELECT to_char(ts,'YYYY-MM-DD"T"HH24:MI:SS"Z"') FROM timedim
         WHERE ts &gt;= to_timestamp(:start_timestamp)
           AND ts &lt;= to_timestamp(:end_timestamp)
      ORDER BY ts DESC
   </validate_query>
 </dimension>
 <!-- "time" dimension, "new-style" definition using an ElasticSearch back-end

      This example defines a "time" dimension whose possible values are
      stored in the http://localhost:9200/times ElasticSearch index. The
      default value is "d1".

      A WMS request with that dimension may contain, e.g.
      "... &time=1999-08-11T11:03:07Z/2001-09-21T08:17:56Z& ..."
 -->
 <dimension type="elasticsearch" name="time" default="d1" time="true">
   <http>
     <url>http://localhost:9200/times/_search</url>
     <headers>
       <Content-Type>application/json</Content-Type>
     </headers>
   </http>

   <list_query><![CDATA[
     { "query": { "match_all": { } } }
   ]]></list_query>
   <list_response><![CDATA[
     [ "hits", "hits", "_source", "ts" ]
   ]]></list_response>

   <validate_query><![CDATA[
     { "query": {
         "range": {
           "ts": { "gte": :start_timestamp, "lte": :end_timestamp }
         }
       },
       "sort": { "ts": { "order": "desc" } },
       "script_fields": {
         "iso_ts": {
           "lang": "painless",
           "source": "SimpleDateFormat f=new SimpleDateFormat(params.fmt); f.setTimeZone(params.tz); return (f.format(doc.ts.value.getMillis()))",
           "params": {
             "fmt": "yyyy-MM-dd'T'HH:mm:ss'Z'",
             "tz: "UTC"
           }
         }
       }
     }
   ]]></validate_query>
   <validate_response><![CDATA[
     [ "hits", "hits", "fields", "iso_ts", 0 ]
   ]]></validate_response>

 </dimension>

模板化维度查询

<validate_query><list_query> 可以包含将在运行时被正确值替换的模板项。有效的模板条目包括:

  • :dim 传入的HTTP请求中提供的维度值

  • :tileset 平铺集名称

  • :gridsrs 栅极SRS

  • :minx:miny:maxx:maxy 矩形范围参数

  • :start_timestamp:end_timestamp 时间间隔参数

Tile Assembly Policies

从维度后端查询返回多个时间或子维度值时,生成的图块是所有与每个值匹配的简单图块的组合。简单切片的组装方式是 <assembly_type> 标签 <dimensions> 元素。目前,mapcache中只实现了两个值:

  • none :不执行任何程序集,生成的图块是第一个检索到的简单图块。这是默认值。

  • stack :结果图块的每个像素都填充了所有简单图块中按检索顺序找到的第一个不透明像素,例如:

    装配类型: stack
    ../_images/mapcache-assembly-stack-1.png ../_images/mapcache-assembly-stack-2.png ../_images/mapcache-assembly-stack-3.png

    Product #1

    Product #2

    产品集装

生成的图块可以缓存,也可以不缓存,具体取决于 <store_assemblies> 标签 <dimensions> 元素。两个可能的值是 truefalse . 默认是 true .

这个 <subdimensions_read_only> 标签 <dimensions> 元素指示在缓存丢失时是否应查询数据源。两个可能的值是 truefalse . 默认是 false .

<dimensions>
    <assembly_type>stack</assembly_type>
    <store_assemblies>true</store_assemblies>
    <subdimensions_read_only>false</subdimensions_read_only>
    <dimension >...</dimension>
</dimensions>

磁贴提取策略

MapCache可以配置为在一个线程中获取所有要组装的子文件,或者使用与要获取的子文件一样多的线程。这是用 <assembly_threaded_fetching> 标签 <dimensions> 元素。此标记有一个可选的 maxzoom 属性指定应在给定的缩放级别上禁用多线程获取。

<dimensions>
    <assembly_threaded_fetching maxzoom="5">true</assembly_threaded_fetching>
    <!-- ... -->
    <dimension >...</dimension>
</dimensions>

在地图级别查询维度

默认情况下,MapCache运行 <validate_query> 为地图的每个请求平铺的第二级维度。当这涉及到慢速的远程PostgreSQL或ElasticSearch服务器时,可能需要为整个映射只发送一次查询。上的配置选项 <dimension> 存在允许此行为的级别:

<dimension>
   <wms_querybymap>true</wms_querybymap>

存储维度

当使用基于磁盘的缓存块时,它将存储在类似于 base/gridname/DIM1/value/xx/xx/xx/xx/xx/xx.png (其中dim1是尺寸值)。

在`<dimensions>``标记内的`<dimension>``标记的顺序很重要,因为它用于为磁盘缓存创建目录结构。如果更改这些值的顺序,则以前缓存过的任何图块都将无效(它们对mapcache不可用,但不会被删除)。

模板可用于更改文件夹结构,例如:

<cache name="tmpl" type="disk">
    <template>/tmp/template-test/{tileset}#{grid}#{dim}/{z}/{x}/{y}.{ext}</template>
</cache>

模板还可用于更改sqlite数据库名称,例如

<!-- the following will create databases named TilesetName-#DimensionValue.db -->
<cache name="sqlite" type="sqlite3">
   <dbfile>{tileset}-{dim}.db</dbfile>
   <detect_blank />
</cache>

访问具有维度的平铺缓存

要检索具有特定维度的图块,请将维度名称和值添加到请求查询字符串,例如 &DIM1=value

只有WMS和WMTS客户端支持将维度传递到MapCache。其他对象服务,如gmap(谷歌地图)、tms和kml不支持尺寸。但是,WMT不允许使用X、Y、Z寻址方案进行访问,因此,通过在基于Web服务器平铺的客户端(例如Openlayers)上使用URL重写来进行访问 ol.source.XYZ 层)可以加载基于维度的tileset。

# a URL such as the following
http://servername/tiles/13/3914/2687.png
# can be rewritten into a WMTS request - note WMTS uses {z}/{y}/{x} rather than {z}/{x}/{y}
# so these values need to be swapped
http://servername/mapcache/wmts/1.0.0/layername/default/dimension/GoogleMapsCompatible/13/2687/3914.png

多维传播Tile Caches

MapCache seeding tool 允许使用以下语法对特定维度进行种子设定:

mapcache_seed -c mapcache_config.xml -t tileset1 -e -1187000,6695000,-605000,7450000 -z 7,10 --dimension DIMENSION_NAME=DIMENSION_VALUE