Select to view content in your preferred language

Name a definition query when created

199
4
12-11-2024 06:50 AM
CarsonGEO
New Contributor

Hello, I am trying to create a definition query for layers in a specific group.  The following works to create the definition query in the group but I was wondering if there is a way to name the query rather than it defaulting to Query 1.

aprx = arcpy.mp.ArcGISProject("CURRENT")

# Access the map
map_obj = aprx.listMaps("Map")[0]

# Define the definition query
definition_query = "field = 'value'"

# Apply the definition query to all layers in a specific group
group_layer_name = "Working"
group_layer = map_obj.listLayers(group_layer_name)[0]

for layer in group_layer.listLayers():
if layer.isFeatureLayer:
layer.definitionQuery = definition_query

Thanks!

0 Kudos
4 Replies
DanPatterson
MVP Esteemed Contributor

did you see example 4 in this link?

Layer—ArcGIS Pro | Documentation


... sort of retired...
CarsonGEO
New Contributor

Yes, I did. I thought it was doing nothing when running it in a notebook but now I need to look back at it, because I tried it again and it is only applying it to the first layer in the TOC.

0 Kudos
HaydenWelch
MVP

Here's a set of functions I use to manage my layer queries:

from pprint import pformat

from arcpy.mp import ArcGISProject
from arcpy._mp import Map, Layer
from typing import Any

def get_project_queries(project: ArcGISProject) -> dict[str: Any]:
    """Gets the queries from a project
    @param project: The project to get the queries from
    @return: The dictionary of queries
    """
    out_dict = {}
    for mp in project.listMaps():
        mp: Map = mp
        out_dict[mp.name] = {}
        for lyr in mp.listLayers():
            lyr: Layer = lyr
            if lyr.supports("definitionQuery") and lyr.definitionQuery:
                out_dict[mp.name][lyr.longName] = lyr.listDefinitionQueries()
    return {k : v for k, v in out_dict.items() if v}

def _merge_definition_queries(queries: dict[str, Any], mp: Map, lyr: Layer) -> list[dict[str, Any]]:
    """Merges multiple enabled queries into one
    Useful for writing out multiple queries into a config file and then merging them into a single query
    @param queries: The queries dictionary
    @param mp: The map
    @param lyr: The layer
    @return: The merged queries
    """
    updates = []
    
    # Get enabled queries
    enabled_queries = \
        [
            (q['name'], q['sql']) 
            for q in queries[mp.name][lyr.longName] 
            if q['isActive']
        ]
        
    # Merge name and query if there are multiple enabled queries for a layer
    merged_name = "/".join([name for name, _ in enabled_queries])
    merged_sql = " AND ".join([sql for _, sql in enabled_queries])  
    
    # Save Updates
    updates.append({"name": merged_name, "sql": merged_sql, "isActive": True})
    
    if updates:
        # Apply merged queries
        updates.extend([q for q in queries[mp.name][lyr.longName] if not q['isActive']])
        queries[mp.name][lyr.longName] = updates
    return queries

def set_project_queries(project: ArcGISProject, queries: dict[str: Any]) -> None:
    """Sets the queries from a project
    @param project: The project to set the queries on
    @param queries: The queries to set
    """
    # Iterate Maps
    for mp in project.listMaps():
        mp: Map = mp
        if mp.name not in queries:
            continue
        # Iterate Map Layers
        for lyr in mp.listLayers():
            lyr: Layer = lyr
            # Skip if the layer is not in the queries dictionary
            if lyr.longName not in queries[mp.name]:
                continue
            # Handle the case where multiple queries are enabled
            if len(queries[mp.name][lyr.longName]) > 1:
                queries = _merge_definition_queries(queries, mp, lyr)
                
            lyr.updateDefinitionQueries(queries[mp.name][lyr.longName])
    return

 

The general idea is to take the output of get_project_queries and write it into a config file somewhere so you can then use the other two functions to load that config back in (json.dumps and json.loads). I kept the pformat import up there so you can use that to format your dump so it's easier to read and edit.

0 Kudos
Clubdebambos
MVP Regular Contributor

Hi @CarsonGEO 

You can indeed. You can use a dictionary and update the list of definition queries for each layer.

definition_query = {"name" : "NAME_IT_HERE", "sql" : "field = 'value'", "isActive" : True}

for layer in group_layer.listLayers():
    ## Get teh current list of DQs (it could be empty)
    definition_query_list = lyr.listDefinitionQueries()

    ## Append in the new DQ
    definition_query_list.append(definition_query)

    ## Update the DQs for the layer
    layer.updateDefinitionQueries(definition_query_list)

Now, only one Definition Query per layer can be Active. If you have multiple per layer you can iterate over these from the list returned by listDefinitionQueries and set the isActive to False for these and then append in the new DQ (as above) and set as Active.

All the best,

Glen

~ learn.finaldraftmapping.com
0 Kudos