---
title: 表达式查询
source: https://vjmap.com/guide/exprQuery.html
---

# 表达式查询

  当CAD图纸以`内存模式`方式直接打开时，因为没有转`空间数据库`这个过程，所以在前端无法可以通过`sql`对后台数据进行自定义查询，只能通过`js脚本`进行查询或通过`表达式`进行查询。表达式语法具体可查看文档[服务端渲染表达式语法](/guide/expr.html)。

::: tip 提示
`js脚本` 更好理解，容易上手，但性能稍慢
`表达式` 较难理解，上手较难，但性能好
推荐用`js脚本`
:::
  
## 内置变量

|变量|说明|类型|举例|
|:---|:---|:---|:---|
|gInLayerIndex|当前实体图层索引|(数值型)|0|
|gInObjectId|当前实体对象ID|(字符串)|'283' 判断如 gInObjectId=='283'
|gInFeatureType|当前实体类型|(字符串)|'AcDbPolyline' 判断如 gInFeatureType=='AcDbPolyline'
|gInLayerName|当前实体图层名称|(字符串)|'图层1' 判断如 gInLayerName=='图层1'
|gInColor|当前实体颜色|(数值型)|4278255615
|gInColorRed|当前实体颜色(红色分量)|(数值型)|255
|gInColorGreen|当前实体颜色(绿色分量)|(数值型)|255
|gInColorBlue|当前实体颜色(蓝色分量)|(数值型)|0
|gInColorAlpha|当前实体颜色(透明度分量)|(数值型)|0
|println|调试输出函数|
|gInExtendMinX|当前实体图形范围(右下角X)|(数值型)|700.10
|gInExtendMinY|当前实体图形范围(右下角y)|(数值型)|10.01
|gInExtendMaxX|当前实体图形范围(左上角X)|(数值型)|800.20
|gInExtendMaxY|当前实体图形范围(左上角y)|(数值型)|20.02
|gInAttrs1|当前实体属性一值|(字符串) s1 线型|
|gInAttrs2|当前实体属性二值|(字符串) s2 扩展字典数据|
|gInAttrs3|当前实体属性三值|(字符串) s3 不同实体表达不一样|
|gInAttrs4|当前实体属性四值|(字符串) s4 字符型属性数据, 不同实体表达不一样|
|gInAttrs5|当前实体属性五值|(字符串) s5 字符型属性数据, 不同实体表达不一样|
|gInAttrn6|当前实体属性六值|(数值型) n1 颜色索引|
|gInAttrn7|当前实体属性七值|(数值型) n2 线型比例|
|gInAttrn8|当前实体属性八值|(数值型) n3 线宽|
|gInAttrn9|当前实体属性九值|(数值型) n4 透明度|
|gInAttrn10|当前实体属性十值|(数值型) n5 数值型属性数据, 不同实体表达不一样|
|gInAttrn11|当前实体属性11值|(数值型) n6 不同实体表达不一样|
|gInAttrn12|当前实体属性12值|(数值型) n7 不同实体表达不一样|
|gInAttrn13|当前实体属性13值|(数值型) n8 不同实体表达不一样|
|gInAttrn14|当前实体属性14值|(数值型) n9 不同实体表达不一样|
|gInAttrn15|当前实体属性15值|(数值型) n10 不同实体表达不一样|
|gInCoordX|当前实体坐标X数组|(数值型数组)|[10,20...]  gInCoordX[0]=10|
|gInCoordY|当前实体坐标Y数组|(数值型数组)|[10,20...]  gInCoordY[0]=10|
|gInCoordZ|当前实体坐标Z数组|(数值型数组)|[10,20...]  gInCoordZ[0]=10|
|gInCoordCount|当前实体坐标个数|(数值型)|2|
|gOutColorRed|返回的颜色(红色分量)(修改当前实体颜色)|(数值型)|255，如gOutColorRed := 255;表示所有级别红色分量为255; 也可以是数组表示，如gOutColorRed[0] := 122;gOutColorRed[5] := 200;表示1-4级别红色分量是122,5级别以上是红色分量200
|gOutColorGreen|返回的颜色(红色分量)(修改当前实体颜色)|(数值型)|255,用法同上
|gOutColorBlue|返回的颜色(红色分量)(修改当前实体颜色)|(数值型)|255,用法同上
|gOutColorAlpha|返回的颜色(透明度分量)(修改当前实体颜色)|(数值型)|255,用法同上
|gOutLineWidth|返回的线宽值(修改当前实体线宽值)|(数值型)|3,用法同上
|gOutVisible|返回是否可见(修改当前实体是否可见)|(数值型)|1或0,用法同上
|gOutReturn|0 不加入选择集;1加入选择集|


## 支持的CAD实体类型

| 类名称                        |说明| 类型值 |
|:---------------------------|:---|:----|
| AcDbLine                   |直线| 1   |
| AcDbPolyline               |多段线| 2   |
| AcDb2dPolyline             |二维折线| 3   |
| AcDb3dPolyline             |三维多段线| 4   |
| AcDbSpline                 |样条曲线| 5   |
| AcDbArc                    |圆弧| 6   |
| AcDbCircle                 |圆| 7   |
| AcDbEllipse                |椭圆| 8   |
| AcDbCurve                  |曲线| 9   |
| AcDbBlockReference         |块参照| 10  |
| AcDbHatch                  |填充| 11  |
| AcDbMText                  |多行文本| 12  |
| AcDbText                   |单行文本| 13  |
| AcDbShape                  |型实体| 14  |
| AcDbRasterImage            |栅格图片| 15  |
| AcDbWipeout                |遮罩实体| 16  |
| AcDb2LineAngularDimension  |角度标注[两条线]| 17  |
| AcDb3PointAngularDimension | 角度标注[三点]| 18  |
| AcDbAlignedDimension       |对齐标注| 19  |
| AcDbArcDimension           |圆弧标注| 20  |
| AcDbDiametricDimension     |直径标注| 21  |
| AcDbOrdinateDimension      |坐标标注| 22  |
| AcDbRadialDimension        |半径标注| 23  |
| AcDbRadialDimensionLarge   |半径折线标注| 24  |
| AcDbRotatedDimension       |转角标注| 25  |
| AcDbAttributeDefinition    |属性注记| 26  |
| AcDbAttribute              |块属性| 27  |
| AcDbTable                  |表格| 28  |
| AcDbMLeader                |引线标注| 29  |
| AcDbRegion                  |面域| 30  |
| AcDbPolyFaceMesh            |多面网格实体| 31  |
| AcDbPolygonMesh             |多边形网格| 32  |
| AcDbSurface                  |曲面| 33  |
| AcDb3dSolid                  |三维实体| 34  |
| AcDbFace                  |三维面| 35  |
| AcDbSolid                |实线实体| 36  |

## 表达式示例说明


查询图中的`所有的直线`
js
```js
return gInFeatureType=='AcDbLine'
```


查询图中`图层名称为图层1`的所有`三维多段线`
```js
return (gInFeatureType=='AcDb3dPolyline' && gInLayerName=='图层1')
```

查询图中`红色`的`单行文本`
```js
return (gInFeatureType=='AcDbText' && gInColorRed==255 &&  gInColorGreen==0 &&  gInColorBlue==0)
```

查询图中`objectid为`的`9BE`的实体
```js
return gInObjectId=='9BE'
```


查询图中所有文本(单行文本、多行文本、属性注记、块属性)
```js
return (gInFeatureType=='AcDbText' || gInFeatureType=='AcDbMText' || gInFeatureType=='AcDbAttributeDefinition' || gInFeatureType=='AcDbAttribute')
```

查询图中所有块实体
```js
return gInFeatureType=='AcDbBlockReference'
```



查询图中`长度为10的直线`
```js
return (gInFeatureType=='AcDbLine' && gInAttrn11 == 10)
```


查询图中`半径为5的圆`
```js
return (gInFeatureType=='AcDbCircle' && gInAttrn12 == 5)
```

图询图中`所有多段线`并且`图层为网格线`，同时`坐标x需大于10`
```js
return (gInFeatureType == 'AcDbPolyline' &&  gInLayerName == '网格线' && gInExtendMinX >= 10)
```


## 查询方法

```ts
 /**
 * 表达式查询实体
 * @param param 参数
 * @param cb 结果中每个点的处理回调。如果返回空的话，则用默认处理方法
 */
exprQueryFeature(param: IExprQueryFeatures, cb?: (point: [number, number]) => [number, number] | null | undefined): Promise<any>;
   /**
 * 表达式查询实体参数
 */
export  interface IExprQueryFeatures extends IQueryBaseFeatures {
    /** 表达式. */
    expr: string;
    /** 记录开始位置. */
    beginpos?: number;
}
```
写表达式时，需要根据条件判断是否返回，格式为:
```js
return true; // 或 return false;
```

如查询图中所有块实体，表达式为 

```js
return gInFeatureType == 'AcDbBlockReference'
```


查询写法为:

```js
let query = await svc.exprQueryFeature({
    // 表达式写法
    // expr: `gOutReturn := if((gInFeatureType == 'AcDbPolyline' and  gInLayerName == '网格线' and gInExtendMinX >= ${center.x} ), 1, 0);`,
    // 现在也支持js语法
    // expr: `if (gInFeatureType == 'AcDbPolyline' &&  gInLayerName == '网格线' && gInExtendMinX >= ${center.x} ) {
    //         return true;
    //     } else {
    //         return false;
    //     }`,
    // 过滤出所有块对象实体(表达式写法)
    // expr: `gOutReturn := if((gInFeatureType == 'AcDbBlockReference'), 1, 0);`,
    // 过滤出所有块对象实体(js写法)
    expr: `return gInFeatureType == 'AcDbBlockReference'`,
    fields: "objectid,blockname,envelop",
    useCache: true,
    limit: 1000000 // 数量大些，相当于查找所有的
})
```


<mapFrameEx>
<pre>
// --后台查询实体数据[内存渲染]--直接在后台以内存方式打开已上传的CAD的DWG格式的图模式下，在后台通过条件查询实体数据
let svc = new vjmap.Service(env.serviceUrl, env.accessToken)
let res = await svc.openMap({
    mapid: env.exampleMapId,
    mapopenway: vjmap.MapOpenWay.Memory, // 以内存渲染方式打开
    style: vjmap.openMapDarkStyle()
})
if (res.error) {
    message.error(res.error)
}
let mapExtent = vjmap.GeoBounds.fromString(res.bounds);
let prj = new vjmap.GeoProjection(mapExtent);
let center = mapExtent.center();
let map = new vjmap.Map({
    container: 'map', // container ID
    style: svc.rasterStyle(),
    center: prj.toLngLat(center),
    zoom: 2,
    renderWorldCopies: false
});
map.attach(svc, prj);
map.fitMapBounds();
map.addControl(new vjmap.NavigationControl());
map.addControl(new vjmap.MousePositionControl({showZoom: true}));
const handleQuery= async () => {
    let query = await svc.exprQueryFeature({
        // 过滤出所有块对象实体
        expr: `return gInFeatureType == 'AcDbBlockReference'`,
        fields: "objectid,blockname,envelop",
        useCache: true,
        limit: 1000000 // 数量大些，相当于查找所有的
    })
    if (query.error) {
        message.error(query.error)
    } else {
        // 根据要过滤的块名称过滤结果
        let polygons = []
        for(let i = 0; i < query.result.length; i++) {
            let blockname = query.result[i].blockname;
            let bounds = map.getEnvelopBounds(query.result[i].envelop);
            polygons.push({
                points: map.toLngLat(bounds.toPointArray()),
                properties: {
                    name: "objectid:" + query.result[i].objectid,
                    color: '#ff00ff'
                }
            });
        }
        map.logInfo(`查询到符合的记数条数：${query.recordCount}`)
        // 绘制查找出来的块
        let polygon = new vjmap.Polygon({
            data: polygons,
            fillColor: ['case', ['to-boolean', ['feature-state', 'hover']], 'yellow', ['get', 'color']],
            fillOpacity: ['case', ['to-boolean', ['feature-state', 'hover']], 0.8, 0.5],
            // 如果一开始不显示这个多边形，可以把透明度设置为0,鼠标移上去才会显示多边形
            // fillOpacity: ['case', ['to-boolean', ['feature-state', 'hover']], 0.8, 0.0],
            fillOutlineColor: ['get', 'color'],
            isHoverPointer: true,
            isHoverFeatureState: true
        });
        polygon.addTo(map);
    }
};
handleQuery()
</pre>
</mapFrameEx>
<br/>
<br/>  


## 表达式查询和Sql查询结合使用

[在线查看示例多种查询块对象子实体面积最大值](https://vjmap.com/demo/#/demo/map/service/22findzmultiquery)

```js
// --多种查询块对象子实体面积最大值--查询块中面积最大的实体，先通过表达式查询，再通过条件查询。一起分析结果
let svc = new vjmap.Service(env.serviceUrl, env.accessToken)
let res = await svc.openMap({
    mapid: env.exampleMapId,
    mapopenway: vjmap.MapOpenWay.GeomRender, // 以几何数据渲染方式打开
    style: vjmap.openMapDarkStyle()
})
if (res.error) {
    message.error(res.error)
}
let mapExtent = vjmap.GeoBounds.fromString(res.bounds);
let prj = new vjmap.GeoProjection(mapExtent);
let center = mapExtent.center();
let map = new vjmap.Map({
    container: 'map', // container ID
    style: svc.rasterStyle(),
    center: prj.toLngLat(center),
    zoom: 2,
    renderWorldCopies: false
});
map.attach(svc, prj);
map.fitMapBounds();

map.addControl(new vjmap.NavigationControl());
map.addControl(new vjmap.MousePositionControl({showZoom: true}));

// let blockNames = ["M_F13", "_AXISO"]; // 要查找的块名称列表 块名称可通过在云端管理平台中点击块实体，右侧属性中的blockname

const handleQuery= async () => {
    let query = await svc.exprQueryFeature({
        expr: `return gInFeatureType == 'AcDbBlockReference'`,
        fields: "objectid,blockname,layername,positon,rotate,scaleX,scaleY,scaleZ", // 为空的话，表达所有字段
        geom: false, // 内存模式
        useCache: true,
        limit: 1000000 // 数量大些，相当于查找所有的
    })
    if (query.error) {
        message.error(query.error)
        return
    }
    // 根据要过滤的块名称过滤结果
    //  let findBlockName = new Set(blockNames);
    let objectIds = new Set(); // 块对象的objectid值
    let blockEntities = [];
    for(let i = 0; i < query.result.length; i++) {
        let blockname = query.result[i].blockname;
        // if (!findBlockName.has(blockname)) {
        // 如果不在要找的里面
        //     continue
        // }
        blockEntities.push(query.result[i])
        objectIds.add(query.result[i].objectid)
    }

    // 下面根据所有块的objectid去条件查询下面块中所包含的具体子实体。这个数据通过内存查询查不到。只有通过几何处理把块分解成了一个个子实体了，通过条件查询去查
    // 条件查询中同一个块实体的objectid都是为此块的objectid_开头的
    // 实体id
    // 块objectid命名规则:块id_引用的块定义id1_引用的块定义id2(可能有多个)_实体id_#;
    // 表格命名规则:objectid命名规则:块id_引用的块定义id1_引用的块定义id2(可能有多个)_实体id_@;
    // 组objectid命名规则:$实体id_实体内元素索引$组id;

    // 构造sql条件，所有块objectid_开头的一次先查出来。提高效率
    // 模糊查找可能like中的匹配符%查找。%符号用于在模式的前后定义通配符。like 'k%'查找以字母 'k' 结尾
    let condtionIds = Array.from(objectIds).map(id => `objectid like '${id}_%' `).join(" or ") // 把所有符合条件的id用字符串连起来

    let condQuery = await svc.conditionQueryFeature({
        condition:  condtionIds, // objectid符合上面的条件就可以。
        fields: "objectid,area",
        geom: true,
        limit: 100000 //设置很大，相当于把所有的都查出来。不传的话，默认只能取100条
    })

    if (query.error) {
        message.error(query.error)
        return
    }
    let blockFeatures = []
    for(let i = 0; i < condQuery.result.length; i++) {
        let item = condQuery.result[i];
        blockFeatures.push(item)
    }

    // 查找所有块下面的相关的实体，找出面积最大的子实体
    let showDatas = []
    for(let block of blockEntities) {
        // 以块objectid_开头的都是块的子实体
        let blockFeature = blockFeatures.filter(b => b.objectid.indexOf(block.objectid + "_") === 0)
        let maxArea = Math.max(...blockFeature.filter(b => b.area).map(d => d.area))
        showDatas.push({
            ...block,
            area: maxArea
        })
    }
    console.table(showDatas)
    message.info(`查询到符合的记数条数：${blockEntities.length} 请按F12查看控制台具体数据`)
};

handleQuery();
```
