在ArcGIS二次開發中,IQueryFilter和ISpatialFilter是最常用的查詢接口。
一、IQueryFilter接口
IQueryFilter接口用於屬性查詢。該接口提供了1個方法和3個屬性。如AddField方法用於向輸出字段集中添加一個字段,OutputSpatialReference屬性用於獲取給定字段的輸出幾何圖形的空間參考,SubFields用於獲取或設置輸出幾何圖形的字段名稱清單,WhereClause用於獲取或設置查詢過濾條件。
對於IQueryFilter.SubFields這個屬性之前一直是被我忽略的,後來在實際應用時才發現,SubFields屬性可以用來提高性能。主要原理是:性能增益來自於獲取所需的字段值,而不是每行的所有數據。
SubFields的默認值爲“*”,表示將返回所有字段值。將其設置回原始(默認)“*”可以通過將其設置爲“*”或“”來完成。還可以是使用IQueryFilter.AddField方法向篩選字段集合中(SubFields)添加字段名。
/// <summary>
///
/// </summary>
/// <param name="pFeatureClass"></param>
public static void Test(IFeatureClass pFeatureClass)
{
List<int> lisOids = new List<int>();
using (ComReleaser comReleaser=new ComReleaser())
{
IQueryFilter queryFilter = new QueryFilterClass();
queryFilter.SubFields = $"{pFeatureClass.ShapeFieldName},{pFeatureClass.OIDFieldName}"; //篩選器的字段名使用逗號分隔,此處設置的是獲取“shape”和“OID”
//queryFilter.AddField(pFeatureClass.OIDFieldName); 向篩選字段集合中添加字段名
//queryFilter.WhereClause = $"{pFeatureClass.OIDFieldName}<1000"; 過濾條件
IFeatureCursor pFeatureCursor = pFeatureClass.Search(queryFilter, true);
IFeature pFeature = null;
while ((pFeature = pFeatureCursor.NextFeature()) != null)
{
lisOids.Add(pFeature.OID);
}
}
}
當設置了SubFields後就獲取不到被過濾掉的字段值了。
二、 ISpatialFilter接口
ISpatialFilter繼承了接口IQueryFilter,在屬性查詢的基礎上加了要素與要素的空間關係進行查詢。Geometry用於設置查詢幾何;SpatialRel設置查詢的空間關係,具體可參考:GIS空間查詢(SpatialFilter)時各種空間關係總結;
GeometryField設置查詢的幾何字段的名稱;SearchOrder屬性用於設置搜索順序,僅僅在ArcSDE中起作用,通常空間查詢優先於屬性查詢。
其中SpatialFilterClass還繼承了接口IQueryFilterDefinition2。
/// <summary>
/// 空間查詢
/// </summary>
/// <param name="pFeatureClass">要素圖層</param>
/// <param name="pGeometry">查詢幾何</param>
public static void UsingISpatialFilter(IFeatureClass pFeatureClass, IGeometry pGeometry)
{
//創建屬性查詢
ISpatialFilter pSpatialFilter = new SpatialFilterClass()
{
SubFields = "", //設置查詢字段
WhereClause = "", //過濾條件
Geometry = pGeometry, //設置查詢幾何
SpatialRel = esriSpatialRelEnum.esriSpatialRelContains, //設置查詢的空間關係
GeometryField = pFeatureClass.ShapeFieldName,
PostfixClause = $"ORDER BY {pFeatureClass.OIDFieldName} desc", //排序
};
//ISpatialFilter轉爲IQueryFilterDefinition接口後設置
//IQueryFilterDefinition2 pQueryFilterDef2 = (IQueryFilterDefinition2)pSpatialFilter;
//pQueryFilterDef2.PostfixClause = $"ORDER BY {pFeatureClass.OIDFieldName} desc";
using (ComReleaser comReleaser = new ComReleaser())
{
IFeatureCursor pFeatureCursor = pFeatureClass.Search(pSpatialFilter, true);
comReleaser.ManageLifetime(pFeatureCursor);
IFeature pFeature = null;
while ((pFeature = pFeatureCursor.NextFeature()) != null)
{
//
}
}
}
三、IQueryFilterDefinition接口
可見IQueryFilter和ISpatialFilter只能執行簡單的屬性查詢。若要執行復雜點的就需要使用IQueryDef接口查詢或則轉爲IQueryFilterDefinition接口。IQueryFilterDefinition接口可設置Order By和Group By語句。
public void UsingIQueryFilterDefinition(IFeatureClass pFeatureClass)
{
//創建屬性查詢
IQueryFilter pQueryFilter = new QueryFilterClass();
//轉爲IQueryFilterDefinition接口
IQueryFilterDefinition2 pQueryFilterDef2 = (IQueryFilterDefinition2)pQueryFilter;
pQueryFilterDef2.PostfixClause = $"ORDER BY {pFeatureClass.OIDFieldName} desc"; //追加查詢子句
using (ComReleaser comReleaser = new ComReleaser())
{
IFeatureCursor pFeatureCursor = pFeatureClass.Search(pQueryFilter, true);
comReleaser.ManageLifetime(pFeatureCursor);
IFeature pFeature = null;
while ((pFeature = pFeatureCursor.NextFeature()) != null)
{
//
}
}
}