ThinkGeo.com    |     Documentation    |     Premium Support

Avoiding Regular Expression Searches

I need to build a search feature into my mapping application. I originally used the RegEx styles to perform the search on my attributes, then apply the RegEx styles.


 


However after rethinking my solution a bit, I decided that I would instead push the found features into the EditLayer so the user can easily perform any editing directly to the features found.


 


The problem I'm having now is how do I get the features based on a SQL Query? The Layer.QueryTools.ExecuteQuery(strMyQuery) only returns the data table, and all the spatial queries, are exactly that, spatial queries.


I want to be able to get a collection of features based on a sql execution on the assoctiated attributes.



Jeremy,



I think you still can keep your current Sql Query way. Because one of the return column is Unique. Then you can get the feature by the Unique column. Here is the code for you. We'll wrap this method to the query tool so that you can easily use it in the next version.Collection<Feature> features = ((ShapeFileFeatureSource)citiesLayer.FeatureSource).GetFeaturesByColumnValue(columnName, columnValue);

Any questions please let me know.



Thanks,

Howard



I thought of that, however wouldn't that require an exact match on the column name? I want to be able to set basic search patterns on the values I'm searching for.


 


i.e in using regular expression    for column [Address]    "24 Marke.*"


or in transactional sql "Address LIKE '24 Marke%'"



Jeremy,



I think I didn't say that clearly. Here is my solution.

1, Use QueryTools.ExecuteQuery(strQuery) to find all the data which matches your SQL statement.

2, Loop all the data row to get the unique value; then find the feature by the GetFeaturesByColumnValue to get the related features.



Hope it helps; here is a method for you; if there is any misunderstanding; please point out.public static Collection<Feature> QueryFeatures(string sql, ShapeFileFeatureLayer layer)
{
            layer.Open();
            DataTable dataTable = layer.QueryTools.ExecuteQuery(sql);
            layer.Close();

            Collection<Feature> returnFeatures = new Collection<Feature>();
            // let's say the "RECID" is the unique column in the result.
            foreach (DataRow dataRow in dataTable.Rows)
            {
                string recId = dataRow["RECID"].ToString();
                Collection<Feature> tempFeatures = layer.FeatureSource.GetFeaturesByColumnValue("RECID", recId);
                if (tempFeatures.Count != 0)
                {
                    returnFeatures.Add(tempFeatures[0]);
                }
            }

            return returnFeatures;
}

Any questions please let me know.



Thanks,

Howard



Are you assuming that there is a row that is unique? 


I have looked through the datatable that was returned by the query, and only the we created was there and there is not a row that is unique. I realize we should have some sort of ID row, and I normally would if I was linking my shapes to an external datasource. however when I'm working directly with a shapefile and not linking it externally we don't always create a unique identifier row, as as far as my understanding of shape files go, there is a a link to the attribute data based on the shapes index in the shape file and the row number in the attribute file.


 


Having said that, I realized that its not actually necessary to use a unique identifier row to link to the data, as I can actually use the column I am searching. Below is the modified version of your code


 


        public static Collection<feature> QueryFeatures(ShapeFileFeatureLayer layer, string ColumnName, string Criteria)         {             string strSQL = string.Empty;             string strCriteria = string.Empty;              if (Criteria.Contains("*"))             {                 strCriteria = Criteria.Replace("*", "%");                 strSQL = String.Format("SELECT * FROM {0} WHERE {1} LIKE '{2}'", Path.GetFileNameWithoutExtension(layer.ShapePathFileName), ColumnName, strCriteria);             }             else             {                 strCriteria = Criteria;                 strSQL = string.Format("SELECT * FROM {0} WHERE {1} = '{2}'", Path.GetFileNameWithoutExtension(layer.ShapePathFileName), ColumnName, strCriteria);             }              layer.Open();             DataTable dataTable = layer.QueryTools.ExecuteQuery(strSQL);             layer.Close();              Collection<feature> returnFeatures = new Collection<feature>();             if (dataTable.Rows.Count > 0)             {                 foreach (DataRow dataRow in dataTable.Rows)                 {                     string recId = dataRow[ColumnName].ToString();                     Collection<feature> tempFeatures = layer.FeatureSource.GetFeaturesByColumnValue(ColumnName, recId);                     if (tempFeatures.Count != 0)                     {                         foreach (Feature featureResults in tempFeatures)                             if (!returnFeatures.Contains<feature>(featureResults))                                 returnFeatures.Add(featureResults);                     }                 }             }              return returnFeatures;         }


I realize this is more modified for my solution, however if you are looking at wrapping a similar sort of query function into map suite, you may want to keep in mind that there is not necessarily a unique column created in the attribute table.


I appologize if I am incorrect in this statement.


 


Anyway. Thanks for the code above though. This should solve my problem.



Just a Thought. Would it be possible to add an overload to the .GetFeaturesByColumnValue(); to allow us to specify the columns we want returned with the feature? at the moment GetFeaturesByColumn Value returns features with no data. And alothough I know how to add my data to the feature is seems rather ineffecient. 


Hi Jeremy, 
  
 Thanks for sharing your code and idea. In my opition, unique column is necessary. Maybe not necessary for querying, but how do you think of updating a specific feature? My method is generic to find the feature which exactly match your querying result. Hope it make sense. 
  
 It’s a good suggestion to add this overload. It will be integrate in the next version. 
  
 Please let me know if you have any questions. 
  
 Thanks, 
 Howard