唯杰地图 logo唯杰地图
VJMAP
EN

mapdata-query

vjmapext/references/batch/mapdata-query.md 7.1 KB200 行
原文

本文回答:mapcadLayer.queryMapEntities / queryMapEntitiesByLayer —— 一条 SQL 从后端拉回批量 DWG 实体。

一、为什么要用它

直接用 svc.conditionQueryFeature 有三个坑:

  1. 类型名是数字 ID:后端表里 name='13' 代表 AcDbText,不是字符串。
  2. 分批请求贵:一次 HTTP + SQL 空间查询有几十 ms 开销;N 次查询 = N × 开销。
  3. 结果需要再处理:坐标系、缺省字段处理。

queryMapEntities 封装了这三点:

const fc = await mapcadLayer.queryMapEntities({
  entTypes: ['AcDbText', 'AcDbMText'],     // 自动翻译成 name='13' or name='12'
  condition: "text like '%标题%'"          // 再 AND 拼 where
});

返回标准 GeoJSON.FeatureCollection。

二、queryMapEntities 选项

选项 类型 说明
entTypes string[] AcDb 类型名数组;SDK 翻译并 or 拼入 where
condition string 额外 SQL where;与 entTypes 以 AND 组合
bounds [x1,y1,x2,y2] 或点数组 范围限定
isContains boolean 范围查询是包含 (true) 还是相交 (false,默认)
fields string 逗号分隔字段名
limit number 单次上限,默认 50000
beginpos number 分页起点
toMapCoordinate boolean 返回 CAD 坐标(默认 true);false = Mercator
includegeom / realgeom boolean 是否返回完整 geojson 几何(coordType=1 时默认 true)
coordType 0 | 1 0=只要位置坐标(轻量),1=真实几何,默认 1
layer string 样式图层名过滤(对应 IQueryBaseFeatures.layer;按图层查更推荐用 queryMapEntitiesByLayer)
zoom number 单次查询 zoom
mapid / version string 指定图/版本(默认当前打开的)
extra Record<string,any> 透传给 conditionQueryFeature 的其它参数

三、常用 entTypes 翻译表

类型名 ID
AcDbLine 1
AcDbPolyline 2
AcDb2dPolyline 3
AcDb3dPolyline 4
AcDbSpline 5
AcDbArc 6
AcDbCircle 7
AcDbEllipse 8
AcDbBlockReference 10
AcDbHatch 11
AcDbMText 12
AcDbText 13
AcDbAttributeDefinition 26
AcDbAttribute 27

翻译过程 SDK 会调 svc.getConstData().entTypeIdMap 并按 service 缓存。

四、按图层查询

const fc = await mapcadLayer.queryMapEntitiesByLayer(
  '道路',                                   // 图层名(不是索引)
  ['AcDbLine', 'AcDbPolyline', 'AcDb2dPolyline'],
  { limit: 20000 }
);
// 内部 where: layerindex=N and (name='1' or name='2' or name='3')

entType 传 undefined → 只按图层过滤。

⚠️ 图层名 vs 索引坑(实采 2026-09-20):layerName 是在 svc.getMapLayers() 里按 l.name 匹配的图层名;查询结果里 properties.layerindex 是数字索引(如 12),把这个索引串当 layerName 传回去会查不到图层并静默返回空 FC(不报错)。实体属性里的图层名要用 getMapLayers()[layerindex].name 反查。

五、combineWhere 拼多条件

const where = vjmapext.combineWhere(
  "text like '%A%'",
  "text like '%B%'",
  ""                         // 空串自动忽略
);
// → (text like '%A%') or (text like '%B%')

六、buildEntTypeCondition 手动拿类型片段

自己拼 SQL:

const typeFrag = await vjmapext.buildEntTypeCondition(map, ['AcDbText','AcDbMText']);
// → "name='13' or name='12'"

const fc = await mapcadLayer.queryMapEntities({
  condition: `(${typeFrag}) and color=-65536`
});

七、分页

单次 limit 最大建议 50000;大数据分页:

async function fetchAll(opts, limit = 10000) {
  const all = [];
  for (let begin = 0; ; begin += limit) {      // 游标按 limit 步进,不能按 features.length
    const fc = await mapcadLayer.queryMapEntities({ ...opts, limit, beginpos: begin });
    all.push(...fc.features);
    if (fc.eof || begin + limit >= (fc.recordCount ?? 0)) break;   // 以 eof / recordCount 判结束
  }
  return all;
}

⚠️ 无法提取几何(既无 geom 也无 location)的记录会在组装 FeatureCollection 时被丢弃,所以 features.length 可能小于本页实际行数——用它判断"最后一页"会提前退出,用它推进 beginpos 会重复取数。

八、返回结构

{
  type: 'FeatureCollection',
  features: Feature[],
  recordCount?: number,      // 总数
  beginpos?: number,
  eof?: boolean
}

每个 Feature:

{
  type: 'Feature',
  id: string | number,              // objectid
  properties: {
    name: string,                   // 'AcDbText' 等可读名
    objectid: string,
    layerindex: number,
    color: number,                  // int32,可能负数
    location?: string,              // "x,y" 或 "x,y;x,y"
    points?: string,
    text?: string, contents?: string,
    height?: number, rotate?: number,
    ...
  },
  geometry: Geometry
}

九、典型场景

1 找出所有 "总平面图" 文字

const fc = await mapcadLayer.queryMapEntities({
  entTypes: ['AcDbText', 'AcDbMText'],
  condition: vjmapext.combineWhere(
    "text like '%总平面图%'",
    "contents like '%总平面图%'"
  )
});

2 取视口内某图层所有线

const bounds = map.getGeoBounds();
const fc = await mapcadLayer.queryMapEntitiesByLayer('wall', ['AcDbLine','AcDbPolyline'], {
  bounds: [bounds.min.x, bounds.min.y, bounds.max.x, bounds.max.y],
  isContains: false
});

3 仅要属性不要几何(速度提升)

const fc = await mapcadLayer.queryMapEntities({
  entTypes: ['AcDbText'],
  fields: 'objectid,text,location,color,layerindex',
  includegeom: false
});

十、常见坑

  1. entTypes 直接传 'AcDbText':queryMapEntities 的 entTypes 必须传数组 ['AcDbText']——单字符串会被逐字符当类型名查表,全部不命中,静默返回空 FeatureCollection。只有 queryMapEntitiesByLayer 的 entType 形参容忍单字符串(内部自动归一为数组)。
  2. bounds 单位:是 CAD 坐标,不是经纬度;要 map.fromLngLat 转。
  3. limit 过大 + includegeom:返回数据 MB 级,网络和 parse 都慢。
  4. name='AcDbText' 永远命中 0 条:后端 name 是数字 ID,不是可读名。
  5. 多个 queryMapEntities 并发:OK,但服务端有 rate limit;超 30 req/s 可能被限流。
  6. fields 必须含 geojson 才出 Feature:行转 Feature 时 SDK 只认 geom/points/location/center/insertionPoint/origin 等几何字段,而 geom 本身是 _processQueryResult 从后端 geojson 字段合成的——fields:"objectid" 这类纯属性清单会让 recordCount=554 但 features 为 0(行全被丢,不报错)。fields 里写 geojson 而非 geom。

相关