瓷砖集尺寸

作者

托马斯堡

联系

t在terriscope.fr的端口

作者

塞思吉尔文

联系

在Compass.ie的sGirvin

作者

杰罗姆·布伊

最后更新

2020-05-25

介绍

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

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

mapcache使用维度来:

  • 使用模板结构创建磁盘和SQLite缓存的目录结构 {{dim}} 替换条目,请参阅 模板结构 在……里面 磁盘高速缓存使用多个SQLite数据库文件 在……里面 SQLite缓存

  • 使用自定义模式创建SQLite缓存的数据库结构 :dim 替换条目,请参阅 自定义架构 在……里面 SQLite缓存

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

在MapCache中启用维度支持

维度在配置文件中启用,位于 蒂莱塞 水平。每个分块集都可以使用 <dimensions> 部分,包括一个或多个 <dimension> 元素。

维度属性

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

  • name (required): The name by which the dimension is referred to in a WMS request (minus the dim_ prefix as specified in WMS 1.1.1 Specification) 。

  • default (必需):如果未在WMS请求中明确提供,则为尺寸的默认值。

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

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

维数类型

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不需要知道映射文件的名称,因此可以在启动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&... 在本例中,每个传感器引用内部“产品”子维上的几个数据。下表给出了一个“ensors”维度后端内容的示例:

传感器尺寸

产品子维度

地点

SPOT-IMG1

地点

SPOT-IMG2

PHR

PRO-IMG1

PHR

PRO-IMG2

PHR

PRO-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 placeholder, queries can contain template entries. See Templating dimension queries 下面一节。

PostgreSQL维度

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

  • <connection>: Connection information of the PostgreSQL database implementing the dimension, as expected by the 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 placeholder, queries can contain template entries. See Templating dimension queries 下面一节。

弹性搜索维度

ElasticSearch维类似于SQLite或PostgreSQL维。特别是,上面部分描述的子维功能也可以与ElasticSearch维度一起使用。ElasticSearch与SQLite和PostgreSQL的主要区别是它的查询语言Query-DSL基于JSON而不是SQL。所以呢, <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 placeholder, queries can contain template entries. See 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 and :end_time_stamp. Returned values shall be in yyyy-mm-ddThh:mm:ssZ time format, as specified in RFC 3339 ,但仅限于UTC。

从MapCache1.8开始,除了SQLite文件之外,时间维度的动态后端可以是PostgreSQL数据库或ElasticSearch索引。使用特定后端配置时间维度是通过设置 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 时间间隔的参数

平铺程序集策略

当从维度后端查询返回多个时间或子维度值时,结果分块是与每个值匹配的所有简单分块的集合。组合简单瓷砖的方式是使用 <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

    第1乘积

    第2乘积

    stack 产品#1和#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>

磁贴提取策略

MapCach可以配置为获取所有子分片以在单个线程内或使用与要获取的子分片一样多的线程进行组合。这是使用 <assembly_threaded_fetching> 的标记。 <dimensions> 元素。此标记具有可选的 maxzoom 属性指定应从给定的缩放级别禁用多线程提取。

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

在地图级别查询维度

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

<dimension>
   <wms_querybymap>true</wms_querybymap>

存储维度

使用基于磁盘的缓存切片时,切片将存储在类似于的文件夹结构中 base/gridname/DIM1/value/xx/xx/xx/xx/xx/xx.png (其中DIM1是尺寸值)。

的顺序 <dimension> 中的标记。 <dimensions> 标记非常重要,因为它用于创建磁盘缓存的目录结构。如果更改这些值的顺序,则以前缓存的所有分幅都将无效(它们将不可用于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(GoogleMaps)、TMS和KML不支持维度。但是,WMTS允许使用x、y、z寻址方案进行访问,因此可以在基于Web服务器切片的客户端(例如OpenLayers)上使用URL重写 ol.source.XYZ 层)可以加载基于维度的平铺集。

# 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

播种具有尺寸的平铺缓存

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

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