Filter / Query FeatureLayer before performing other queries

1055
7
02-25-2022 10:22 AM
luckachi
Occasional Contributor III

I have a map that utilizes a FeatureLayer for multiple queries that are performed by selecting items from dropdowns and clicking a button to perform the query. I'd like to filter/query this FeatureLayer right off the bat because I only want the queries to use records that have been verified (and not display unverified records). However, the definitionExpression does not seem to work and the other queries that are performed on this feature layer are still returning un-verified records

 

 

    const obsLayer = new FeatureLayer({
        url: "my MapServer url",
        definitionExpression: "VERIFIED=1 OR VERIFIED=2",
        outFields: ["*"],
        visible: false
      });

 

 

 

I also tried added the query to the FeatureLayer URL ( /query?where= ) but I received a message in the console log that it stripped the parameters.

 

0 Kudos
7 Replies
UndralBatsukh
Esri Regular Contributor

Hi there, 

FeatureLayer.definitionExpression should work. When set correctly, the app will only fetch features that meet the definitionExpression requirements. For subsequent queries or your other queries, generate your query object by calling FeatureLayer.createQuery() method as this method creates a query object that honors your layer settings.

0 Kudos
luckachi
Occasional Contributor III

Hello,

I can't seem to get it to honor the definitionExpression by switching from = new Query() to = obsLayer.createQuery(); 

I have one query at the start of my code that I changed:

      /* Observation Layer */
      const obsLayer = new FeatureLayer({
        url: ".../MISIN_browsedata/MapServer/0",
        outFields: ["*"],
        definitionExpression: "VERIFIED = 2",
        visible: false
      });

      /* Set query parameters to always return geometry and all fields.
      Returning geometry allows us to display results on the map/view */
      // var params = new Query({
      //   returnGeometry: true,
      //   outFields: ["*"]
      // });

      let params = obsLayer.createQuery();
        params.returnGeometry = true;
        params.outFields = ["*"];

 

and one search query section : 

/*** SEARCH BY Common Name ***/

      /* Query features from the observation layer */
      view
       .when(function () {
         return obsLayer.when(function () {
           //var query2 = new Query();
           let query2 = obsLayer.createQuery();
           query2.where = "1=1";
           query2.outFields = ["Q_NAME"];
           query2.returnDistinctValues = true;
           query2.returnGeometry = false;
           query2.orderByFields = ["Q_NAME"];
           return obsLayer.queryFeatures(query2);
           document.getElementById("doBtn2").addEventListener("click", doQueryCommon);
         });
       })
       .then(addToSelect2)

      function addToSelect2(values) {
        var option = document.createElement("option");
        option.text = "--Select--";
        commonSelect.add(option);
        values.features.forEach(function(value) {
        var option = document.createElement("option");
        option.text = value.attributes.Q_NAME;
        commonSelect.add(option);
        });
      }

      /* Call doQueryCommon() each time the button is clicked */
      view.when(function () {
       view.ui.add("optionsDiv", "top-right");
       document.getElementById("doBtn2").addEventListener("click", doQueryCommon);
      });

      /* Executes each time the button is clicked.
      Clears results from prev. query then builds a new query.
      Executes query and calls getResults() once promise is resolved. */
      function doQueryCommon() {
        resultsLayer.removeAll();
        var commonSelectOption = commonSelect.value.replace(/'/g, "''") //for species with apostrophes
        params.where = "Q_NAME =" + "'" + commonSelectOption + "'";
        obsLayer.queryFeatures(params).then(getResultsCommon).catch(promiseRejectedCommon);
        loader.active = true;
      }

      /* Called each time promise is resolved.
      Loop through each results and assign symbol and PopupTemplate */
      function getResultsCommon(response) {
        var cnResults = response.features.map(function (feature) {
          feature.symbol = sym;
          feature.popupTemplate = popupTemplate;
          return feature;
        });
       resultsLayer.addMany(cnResults);

       /* Populate DGrid Table at bottom of page with query results*/
        var items = cnResults
        var TableFeatures = []
        array.forEach(items, function (feature) {
          var TableAttributes = {}
          var TableFields = Object.keys(feature.attributes)
          for (var i = 0; i < TableFields.length; i++) {
            TableAttributes[TableFields[i]] = feature.attributes[TableFields[i]]
          }
        TableFeatures.push(TableAttributes)
        })

        // array empty or does not exist
        if (TableFeatures === undefined || TableFeatures.length == 0) {
          loader.active = false;
          myAlert.show();
        }

        var speciesmemStore = new Memory({
          data: TableFeatures,
          idProperty: "OBJECTID"
        });
        grid.set("collection", speciesmemStore);
        grid.set("sort", "OBJECTID", true) // sorts objectID column - shows most recent 1st
        grid.on("dgrid-select", selectedOBS);
        grid.on('dgrid-deselect', clearonChange);

        /* Zoom to Extent */
        var AOI = response.features;
        view.goTo(AOI);
      }

      /* Called each time promise is rejected */
      function promiseRejectedCommon(error) {
        console.error("Promise rejected: ", error.message);
      }

 

0 Kudos
UndralBatsukh
Esri Regular Contributor

I cannot reproduce the issue you are reporting. layer.createQuery honors all layers settings. What version of the 4.x api are you using? Is your definitiionExpression valid? If it is not then it won't make a difference. 

Here is a simple test app shows how createQuery works: https://codepen.io/U_B_U/pen/BamqVQK?editors=100.

You can see that definitionExpression is honored in the query network request.

Screen Shot 2022-02-28 at 7.16.51 AM.png

0 Kudos
luckachi
Occasional Contributor III

I am currently used 4.22.

When I open the network request, it displays 

 

I have the definitionExpression set to this so it will ignore any record that has a 3 or 4 in the verified column, yet when I query, records with 3 and 4 continue to be displayed.

definitionExpression: "VERIFIED <> 3 OR VERIFIED <> 4",

 

the network request displays:

luckachi_0-1646062406370.png

 

0 Kudos
luckachi
Occasional Contributor III

When I initially load the map however, I see this.

luckachi_1-1646063332041.png

 

so it seems like the params.where line for each additional query isn't retaining that information?

0 Kudos
UndralBatsukh
Esri Regular Contributor

Very hard to tell what is going on. Can you please a provide a reproducible case if you need more help. Seems like definitionExpression changed somewhere before your queryFeatures is called.

0 Kudos
luckachi
Occasional Contributor III

A few messages up I have the featurelayer set up, params and the full section of just one of the many queries I have set up.

0 Kudos