---
title: Expression Query
source: https://vjmap.com/en/guide/exprQuery.html
---

# Expression Query

When CAD drawings are opened directly in `memory mode`, there is no process of converting to a `spatial database`, so the frontend cannot perform custom queries on backend data via `sql`. Queries can only be performed through `js scripts` or through `expressions`. For expression syntax details, see the document [Server-side Rendering Expression Syntax](/en/guide/expr.html).

::: tip Tip
`js scripts` are easier to understand and get started with, but slightly slower in performance
`Expressions` are harder to understand and master, but perform better
We recommend using `js scripts`
:::
  
## Built-in Variables

| Variable | Description | Type | Example |
|:---|:---|:---|:---|
|gInLayerIndex|Current entity layer index|(numeric)|0|
|gInObjectId|Current entity object ID|(string)|'283' e.g. gInObjectId=='283'
|gInFeatureType|Current entity type|(string)|'AcDbPolyline' e.g. gInFeatureType=='AcDbPolyline'
|gInLayerName|Current entity layer name|(string)|'Layer1' e.g. gInLayerName=='Layer1'
|gInColor|Current entity color|(numeric)|4278255615
|gInColorRed|Current entity color (red component)|(numeric)|255
|gInColorGreen|Current entity color (green component)|(numeric)|255
|gInColorBlue|Current entity color (blue component)|(numeric)|0
|gInColorAlpha|Current entity color (alpha component)|(numeric)|0
|println|Debug output function|
|gInExtendMinX|Current entity extent (bottom-right X)|(numeric)|700.10
|gInExtendMinY|Current entity extent (bottom-right Y)|(numeric)|10.01
|gInExtendMaxX|Current entity extent (top-left X)|(numeric)|800.20
|gInExtendMaxY|Current entity extent (top-left Y)|(numeric)|20.02
|gInAttrs1|Current entity attribute 1 value|(string) s1 linetype|
|gInAttrs2|Current entity attribute 2 value|(string) s2 extended dictionary data|
|gInAttrs3|Current entity attribute 3 value|(string) s3 varies by entity type|
|gInAttrs4|Current entity attribute 4 value|(string) s4 string attribute data, varies by entity type|
|gInAttrs5|Current entity attribute 5 value|(string) s5 string attribute data, varies by entity type|
|gInAttrn6|Current entity attribute 6 value|(numeric) n1 color index|
|gInAttrn7|Current entity attribute 7 value|(numeric) n2 linetype scale|
|gInAttrn8|Current entity attribute 8 value|(numeric) n3 line width|
|gInAttrn9|Current entity attribute 9 value|(numeric) n4 transparency|
|gInAttrn10|Current entity attribute 10 value|(numeric) n5 numeric attribute data, varies by entity type|
|gInAttrn11|Current entity attribute 11 value|(numeric) n6 varies by entity type|
|gInAttrn12|Current entity attribute 12 value|(numeric) n7 varies by entity type|
|gInAttrn13|Current entity attribute 13 value|(numeric) n8 varies by entity type|
|gInAttrn14|Current entity attribute 14 value|(numeric) n9 varies by entity type|
|gInAttrn15|Current entity attribute 15 value|(numeric) n10 varies by entity type|
|gInCoordX|Current entity X coordinate array|(numeric array)|[10,20...]  gInCoordX[0]=10|
|gInCoordY|Current entity Y coordinate array|(numeric array)|[10,20...]  gInCoordY[0]=10|
|gInCoordZ|Current entity Z coordinate array|(numeric array)|[10,20...]  gInCoordZ[0]=10|
|gInCoordCount|Current entity coordinate count|(numeric)|2|
|gOutColorRed|Output color (red component) (modify current entity color)|(numeric)|255, e.g. gOutColorRed := 255; means all levels have red component 255; can also be array, e.g. gOutColorRed[0] := 122;gOutColorRed[5] := 200; means levels 1-4 have red 122, level 5+ has red 200
|gOutColorGreen|Output color (green component) (modify current entity color)|(numeric)|255, same usage as above
|gOutColorBlue|Output color (blue component) (modify current entity color)|(numeric)|255, same usage as above
|gOutColorAlpha|Output color (alpha component) (modify current entity color)|(numeric)|255, same usage as above
|gOutLineWidth|Output line width (modify current entity line width)|(numeric)|3, same usage as above
|gOutVisible|Output visibility (modify current entity visibility)|(numeric)|1 or 0, same usage as above
|gOutReturn|0 do not add to selection set; 1 add to selection set|


## Supported CAD Entity Types

| Class Name                        | Description | Type Value |
|:---------------------------|:---|:----|
| AcDbLine                   | Line | 1   |
| AcDbPolyline               | Polyline | 2   |
| AcDb2dPolyline             | 2D Polyline | 3   |
| AcDb3dPolyline             | 3D Polyline | 4   |
| AcDbSpline                 | Spline | 5   |
| AcDbArc                    | Arc | 6   |
| AcDbCircle                 | Circle | 7   |
| AcDbEllipse                | Ellipse | 8   |
| AcDbCurve                  | Curve | 9   |
| AcDbBlockReference         | Block Reference | 10  |
| AcDbHatch                  | Hatch | 11  |
| AcDbMText                  | Multiline Text | 12  |
| AcDbText                   | Single-line Text | 13  |
| AcDbShape                  | Shape | 14  |
| AcDbRasterImage            | Raster Image | 15  |
| AcDbWipeout                | Wipeout | 16  |
| AcDb2LineAngularDimension  | Angular Dimension [two lines] | 17  |
| AcDb3PointAngularDimension | Angular Dimension [three points] | 18  |
| AcDbAlignedDimension       | Aligned Dimension | 19  |
| AcDbArcDimension           | Arc Dimension | 20  |
| AcDbDiametricDimension     | Diametric Dimension | 21  |
| AcDbOrdinateDimension      | Ordinate Dimension | 22  |
| AcDbRadialDimension        | Radial Dimension | 23  |
| AcDbRadialDimensionLarge   | Radial Dimension Large | 24  |
| AcDbRotatedDimension       | Rotated Dimension | 25  |
| AcDbAttributeDefinition    | Attribute Definition | 26  |
| AcDbAttribute              | Block Attribute | 27  |
| AcDbTable                  | Table | 28  |
| AcDbMLeader                | MLeader | 29  |
| AcDbRegion                  | Region | 30  |
| AcDbPolyFaceMesh            | Polyface Mesh | 31  |
| AcDbPolygonMesh             | Polygon Mesh | 32  |
| AcDbSurface                  | Surface | 33  |
| AcDb3dSolid                  | 3D Solid | 34  |
| AcDbFace                  | 3D Face | 35  |
| AcDbSolid                | Solid | 36  |

## Expression Examples


Query `all lines` in the drawing
js
```js
return gInFeatureType=='AcDbLine'
```


Query all `3D polylines` with `layer name "Layer1"` in the drawing
```js
return (gInFeatureType=='AcDb3dPolyline' && gInLayerName=='Layer1')
```

Query `red` `single-line text` in the drawing
```js
return (gInFeatureType=='AcDbText' && gInColorRed==255 &&  gInColorGreen==0 &&  gInColorBlue==0)
```

Query entity with `objectid` of `9BE` in the drawing
```js
return gInObjectId=='9BE'
```


Query all text in the drawing (single-line text, multiline text, attribute definition, block attribute)
```js
return (gInFeatureType=='AcDbText' || gInFeatureType=='AcDbMText' || gInFeatureType=='AcDbAttributeDefinition' || gInFeatureType=='AcDbAttribute')
```

Query all block entities in the drawing
```js
return gInFeatureType=='AcDbBlockReference'
```



Query `lines with length 10` in the drawing
```js
return (gInFeatureType=='AcDbLine' && gInAttrn11 == 10)
```


Query `circles with radius 5` in the drawing
```js
return (gInFeatureType=='AcDbCircle' && gInAttrn12 == 5)
```

Query all `polylines` in the drawing with `layer "grid lines"` and `coordinate x greater than 10`
```js
return (gInFeatureType == 'AcDbPolyline' &&  gInLayerName == 'grid lines' && gInExtendMinX >= 10)
```


## Query Method

```ts
 /**
 * Expression query for entities
 * @param param Parameters
 * @param cb Callback for processing each point in the result. If null is returned, the default handler is used
 */
exprQueryFeature(param: IExprQueryFeatures, cb?: (point: [number, number]) => [number, number] | null | undefined): Promise<any>;
   /**
 * Expression query entity parameters
 */
export  interface IExprQueryFeatures extends IQueryBaseFeatures {
    /** Expression. */
    expr: string;
    /** Record start position. */
    beginpos?: number;
}
```
When writing expressions, you need to return based on condition evaluation. Format:
```js
return true; // or return false;
```

For example, to query all block entities in the drawing, the expression is:

```js
return gInFeatureType == 'AcDbBlockReference'
```


Query usage:

```js
let query = await svc.exprQueryFeature({
    // Expression syntax
    // expr: `gOutReturn := if((gInFeatureType == 'AcDbPolyline' and  gInLayerName == 'grid lines' and gInExtendMinX >= ${center.x} ), 1, 0);`,
    // Now also supports js syntax
    // expr: `if (gInFeatureType == 'AcDbPolyline' &&  gInLayerName == 'grid lines' && gInExtendMinX >= ${center.x} ) {
    //         return true;
    //     } else {
    //         return false;
    //     }`,
    // Filter all block entities (expression syntax)
    // expr: `gOutReturn := if((gInFeatureType == 'AcDbBlockReference'), 1, 0);`,
    // Filter all block entities (js syntax)
    expr: `return gInFeatureType == 'AcDbBlockReference'`,
    fields: "objectid,blockname,envelop",
    useCache: true,
    limit: 1000000 // Large value, equivalent to finding all
})
```


<mapFrameEx>
<pre>
// --Backend query entity data [memory rendering]--Query entity data by conditions in the backend when opening uploaded CAD DWG files directly in memory mode
let svc = new vjmap.Service(env.serviceUrl, env.accessToken)
let res = await svc.openMap({
    mapid: env.exampleMapId,
    mapopenway: vjmap.MapOpenWay.Memory, // Open in memory rendering mode
    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({
        // Filter all block entities
        expr: `return gInFeatureType == 'AcDbBlockReference'`,
        fields: "objectid,blockname,envelop",
        useCache: true,
        limit: 1000000 // Large value, equivalent to finding all
    })
    if (query.error) {
        message.error(query.error)
    } else {
        // Filter results by block name
        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 result count: ${query.recordCount}`)
        // Draw the found blocks
        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],
            // If you don't want to show the polygon initially, set opacity to 0, it will show on hover
            // 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/>  


## Combining Expression Query and SQL Query

[View online demo: Multiple queries for maximum sub-entity area of block objects](https://vjmap.com/demo/#/demo/map/service/22findzmultiquery)

```js
// --Multiple queries for maximum sub-entity area of block objects--Query the entity with the largest area in blocks, first via expression query, then via condition query. Analyze results together
let svc = new vjmap.Service(env.serviceUrl, env.accessToken)
let res = await svc.openMap({
    mapid: env.exampleMapId,
    mapopenway: vjmap.MapOpenWay.GeomRender, // Open in geometry rendering mode
    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"]; // Block name list to find. Block names can be found in the cloud management platform by clicking a block entity and checking blockname in the right-side properties

const handleQuery= async () => {
    let query = await svc.exprQueryFeature({
        expr: `return gInFeatureType == 'AcDbBlockReference'`,
        fields: "objectid,blockname,layername,positon,rotate,scaleX,scaleY,scaleZ", // Empty means all fields
        geom: false, // Memory mode
        useCache: true,
        limit: 1000000 // Large value, equivalent to finding all
    })
    if (query.error) {
        message.error(query.error)
        return
    }
    // Filter results by block name
    //  let findBlockName = new Set(blockNames);
    let objectIds = new Set(); // Block object objectid values
    let blockEntities = [];
    for(let i = 0; i < query.result.length; i++) {
        let blockname = query.result[i].blockname;
        // if (!findBlockName.has(blockname)) {
        // If not in the target list
        //     continue
        // }
        blockEntities.push(query.result[i])
        objectIds.add(query.result[i].objectid)
    }

    // Below, condition query for specific sub-entities contained in all blocks by objectid. This data cannot be obtained via memory query. Only after geometry processing decomposes blocks into individual sub-entities can condition query be used
    // In condition query, sub-entities of the same block all have objectid prefixed with that block's objectid_
    // Entity id
    // Block objectid naming rule: block_id_referenced_block_def_id1_referenced_block_def_id2(may have multiple)_entity_id_#;
    // Table naming rule: objectid naming rule: block_id_referenced_block_def_id1_referenced_block_def_id2(may have multiple)_entity_id_@;
    // Group objectid naming rule: $entity_id_element_index_in_entity$group_id;

    // Build sql condition, query all block objectid_ prefixed at once for efficiency
    // For fuzzy search, % can be used as wildcard in like. % defines wildcards before/after the pattern. like 'k%' finds strings ending with 'k'
    let condtionIds = Array.from(objectIds).map(id => `objectid like '${id}_%' `).join(" or ") // Concatenate all matching ids

    let condQuery = await svc.conditionQueryFeature({
        condition:  condtionIds, // objectid matching the above condition
        fields: "objectid,area",
        geom: true,
        limit: 100000 // Set large, equivalent to getting all. Default 100 if not specified
    })

    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)
    }

    // Find related entities under all blocks, find the sub-entity with maximum area
    let showDatas = []
    for(let block of blockEntities) {
        // All starting with block objectid_ are sub-entities of that block
        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(`Query result count: ${blockEntities.length} Press F12 to view console for details`);
};

handleQuery();
```
