Select to view content in your preferred language

Implementing classBreakRenderer sends extra query req to feature layer

394
0
11-18-2022 07:19 AM
Mayur_Shinde
New Contributor

I have upgraded the JavaScript API to 4.22 version from 4.5. The existing functionality of implementing classBreakRenderer using smart mapping is having performance issue.

I observed that there are extra 8-9 query requests sent to the server which my code has not created.

Here is step-wise implementation

API is integrated in ReactJS App

Here is the functionality implementation

I have put inline comment relevant to this post in blow code itself, starting with  //** Note

const sellAccrualFeatureLayer = new FeatureLayer({
      url: '........../MapServer/4',
      id: 'sellAccrualFeatureLayer',
      outFields: ['*'],
      legendEnabled: true,
      visible: false
    })
    sellAccrualFeatureLayer.opacity = 0.5
    sellAccrualFeatureLayer.definitionExpression = '1=2'
    esrijs.map.add(sellAccrualFeatureLayer)
    esrijs.sellAccrualFeatureLayer = sellAccrualFeatureLayer

Saved in esrijs variable and added to map with visible false.

2) On click of feature I have identify request to another layer to get the attribute of that feature and this acts as input where clause for sellAccrualFeatureLayer created in step 1

And here is the first query for sellAccrualFeatureLayer layer

makeQuerys = () => {
    const sellAccrualFeatureLayer = esrijs.sellAccrualFeatureLayer
    const colorRendererCreator = window.require('esri/smartMapping/renderers/color')
    const legendContainer = this.legendContainer
    const map = esrijs.map
    const dispatch = this.props.dispatch
    const kauppapaikkaNro = this.props.selectedStore.feature.attributes.Kauppapaikkanro
    const queryTimeStamps = sellAccrualFeatureLayer.createQuery()
    queryTimeStamps.where = 'Kauppa=' + kauppapaikkaNro
    queryTimeStamps.spatialRelationship = 'intersects'
    queryTimeStamps.outFields = ['Aikaleima']
    queryTimeStamps.returnDistinctValues = true
    queryTimeStamps.returnGeometry = false
    queryTimeStamps.orderByFields = ['Aikaleima DESC']

    const colorSchemes = window.require('esri/smartMapping/symbology/color')

    const schemes = colorSchemes.getSchemes({
      basemap: map.basemap,
      geometryType: sellAccrualFeatureLayer.geometryType,
      theme: 'high-to-low'
    })

    // console.log(schemes)
    // console.log(schemes.secondarySchemes.find(sc => sc.id === 'high-to-low/gray/seq-browns-bright'))
    sellAccrualFeatureLayer.queryFeatures(queryTimeStamps)
      .then(function (responseTimeStamps) {
        if (responseTimeStamps.features.length > 0 && responseTimeStamps.features[0].attributes.Aikaleima) {
          const params = {
            layer: sellAccrualFeatureLayer,
            field: 'Kertyma',
            view: esrijs.view,
            classificationMethod: 'natural-breaks',
            numClasses: 4,
            legendOptions: {
              title: 'Kertymä'
            },
            // colorScheme: {...schemes.secondarySchemes.find(sc => sc.id === 'high-to-low/' + schemes.basemapId + '/seq-browns-bright'), ...{opacity: 0.95}}
            colorScheme: {...schemes.secondarySchemes.find(sc => sc.id === 'high-to-low/gray/seq-browns-bright'), ...{opacity: 0.95}}
          }

          // generate the renderer and set it on the layer
// ** Note this create renderer request to layer is executed within 1 sec so no issue here
          colorRendererCreator.createClassBreaksRenderer(params)
            .then(function (response) {
              const renderer = response.renderer
              renderer.defaultSymbol = null
              sellAccrualFeatureLayer.renderer = renderer

              if (!esrijs.legend || esrijs.legend.destroyed) {
                const Legend = window.require('esri/widgets/Legend')
                esrijs.legend = new Legend({
                  view: esrijs.view,
                  container: legendContainer
                })
              }
            }).catch(console.error)

          const timeStamps = responseTimeStamps.features.map(x => x.attributes.Aikaleima)
          const latestTimestamp = timeStamps[0]
          const comparisonTimestamp = timeStamps.length > 1 ? timeStamps[1] : latestTimestamp

          const zipcodeWhere = 'Kauppa=' + kauppapaikkaNro + ' and Aikaleima=' + latestTimestamp + ' and Rank <=40'
          sellAccrualFeatureLayer.definitionExpression = zipcodeWhere

          const queryZipcodeSellAccrual = sellAccrualFeatureLayer.createQuery()
          queryZipcodeSellAccrual.where = zipcodeWhere
          queryZipcodeSellAccrual.spatialRelationship = 'intersects'
          queryZipcodeSellAccrual.outFields = ['*']
          queryZipcodeSellAccrual.returnGeometry = false
          queryZipcodeSellAccrual.orderByFields = ['Rank']

// ** Note - observed from the Network tab, that when this below query is executed and req is sent, those extra query requests (PFA RankQueryreq.png are initiated and are in a pending state - and when these extra req are completed then only after that the req in the below Promise.All() are excuted, hence taking more time)

          sellAccrualFeatureLayer.queryFeatures(queryZipcodeSellAccrual)
            .then(function (responseZipcodeSellAccrual) {
              esrijs.sellAccrualFeatureLayer.visible = true
              const top40AccrualData = responseZipcodeSellAccrual.features.map(x => x.attributes).reduce((acc, curr) => {
                acc[curr.Postinumero] = true
                return acc
              }, {})
              const top40AccrualZipcodes = Object.keys(top40AccrualData)

              const queryZipcodeSellAccrualOver40 = sellAccrualFeatureLayer.createQuery()
              queryZipcodeSellAccrualOver40.where = 'Kauppa=' + kauppapaikkaNro + ' and Aikaleima=' + latestTimestamp + ' and Rank >40'
              queryZipcodeSellAccrualOver40.spatialRelationship = 'intersects'
              queryZipcodeSellAccrualOver40.outFields = ['*']
              queryZipcodeSellAccrualOver40.returnGeometry = false
              queryZipcodeSellAccrualOver40.outStatistics = statisticDefinitionOver40

              const queryComparisonZipcodeSellAccrualTop40 = sellAccrualFeatureLayer.createQuery()
              queryComparisonZipcodeSellAccrualTop40.where = 'Kauppa=' + kauppapaikkaNro + ' and Aikaleima=' + comparisonTimestamp + ' and Postinumero IN (\'' + top40AccrualZipcodes.join('\',\'') + '\')'
              queryComparisonZipcodeSellAccrualTop40.spatialRelationship = 'intersects'
              queryComparisonZipcodeSellAccrualTop40.outFields = ['*']
              queryComparisonZipcodeSellAccrualTop40.returnGeometry = false
              queryComparisonZipcodeSellAccrualTop40.orderByFields = ['Rank']

              const queryComparisonZipcodeSellAccrualOver40 = sellAccrualFeatureLayer.createQuery()
              queryComparisonZipcodeSellAccrualOver40.where = 'Kauppa=' + kauppapaikkaNro + ' and Aikaleima=' + comparisonTimestamp + ' and Postinumero NOT IN (\'' + top40AccrualZipcodes.join('\',\'') + '\')'
              queryComparisonZipcodeSellAccrualOver40.spatialRelationship = 'intersects'
              queryComparisonZipcodeSellAccrualOver40.outFields = ['*']
              queryComparisonZipcodeSellAccrualOver40.returnGeometry = false
              queryComparisonZipcodeSellAccrualOver40.outStatistics = statisticDefinitionOver40

//** Note - These are the 3 req that start only after the extra req are completed

              Promise.all([
                sellAccrualFeatureLayer.queryFeatures(queryZipcodeSellAccrualOver40),
                sellAccrualFeatureLayer.queryFeatures(queryComparisonZipcodeSellAccrualTop40),
                sellAccrualFeatureLayer.queryFeatures(queryComparisonZipcodeSellAccrualOver40)
              ]).then(([currentAccrualSumOver40, comparisonAccrualTop40, comparisonAccrualSumOver40]) => {
                console.log("after promise");
                const currentTop40Attributes = responseZipcodeSellAccrual.features.map(x => x.attributes)
                const comparisonTop40Attributes = comparisonAccrualTop40.features.map(x => x.attributes)

                const currentSumEurot = currentTop40Attributes.reduce((acc, curr) => acc + curr.Eurot, currentAccrualSumOver40.features[0].attributes.SUMMA_Eurot)
                const comparisonSumEurot = comparisonTop40Attributes.reduce((acc, curr) => acc + curr.Eurot, comparisonAccrualSumOver40.features[0].attributes.SUMMA_Eurot)

                const data = {
                  currentAccrualTop40: currentTop40Attributes.reduce((acc, curr) => {
                    acc[curr.Postinumero] = calculateAdditionalFields(curr, currentSumEurot)
                    return acc
                  }, {}),
                  currentAccrualSumOver40: calculateAdditionalFields({
                    ...currentAccrualSumOver40.features[0].attributes,
                    usedTimestamp: latestTimestamp
                  }, currentSumEurot, true),
                  comparisonAccrualTop40: comparisonTop40Attributes.reduce((acc, curr) => {
                    acc[curr.Postinumero] = calculateAdditionalFields(curr, comparisonSumEurot)
                    return acc
                  }, {}),
                  comparisonAccrualSumOver40: calculateAdditionalFields({
                    ...comparisonAccrualSumOver40.features[0].attributes,
                    usedTimestamp: comparisonTimestamp
                  }, comparisonSumEurot, true)
                }
                dispatch(setSellAccrualData(data))
              })
            }).catch(console.error)
        }

 

Attachment info

1) extraquery.png - Showing the extra req and req from promises

2) extraquerydetail.png - Details of one of the extra req

3) queryreq.png

 

I tried sending a list of outFields in all queries in the code, including in FeatureLayer Constructor - issue persists.

The issue is why it is sending extra req and those too for "ID" fields as orderby and this field is OID of that layer.

Will be grateful if anyone can help.

0 Kudos
0 Replies