Select to view content in your preferred language

FeatureLayer : Without ObjectId Field?

8338
29
04-02-2012 05:22 AM
__Rich_
Deactivated User
Hi,

I've got a layer within an AGS service that returns a load of point features based on dynamically changing data held in a non-spatial database via an ODBC connection, I'd like to connect a FeatureLayer to the service but it only renders a single feature in the map.

I can see from some investigations that the ESRI JavaScript relies (very heavily) on there being one field in the data that can be used as the 'ObjectIdField' to uniquely identify rows, there isn't an appropriate field in my data and I don't really want to arbitrarily generate something for these data.

Anyone found a way around this restriction?

Thanks.
0 Kudos
29 Replies
derekswingley1
Deactivated User

Creating a surrogate key where it's appropriate for the data is acceptable, but in this case it'd be a hack, the (identity) value would have no 'meaning' to the data values etc.

How would adding a unique key be a surrogate? Fulfilling the requirements for specific functionality isn't a hack. We don't explicitly document that an object ID is required but it is implied in that the main use case for feature layers is using data from ArcGIS Server. As you've outlined, it's possible to publish data with AGS that doesn't have an object ID. We'll update the docs.


The underlying issue is that although the FeatureLayer JS knows that the data has no OID value (and logs this fact to the console) it continues to try and use it as a key to the data, I can point you towards the method(s) in the class where this causes issues if that helps?

I understand the need for a key to identify data if, for example, I was providing some editing of persistable features, but in this case all I want to do is display the features in the map, just like the ArcGISDynamicServiceLayer would, but because I need some client-side functionality not available with an image-based layer type the FeatureLayer appeared to be the best choice....apart from this (rather severe) issue!

A couple more questions:  what's the mode for your feature layer? What kind of things are you wanting to do client side?
0 Kudos
__Rich_
Deactivated User
How would adding a unique key be a surrogate?

That's the correct terminology to use when employing this mechanism, what would you call it? 🙂

Fulfilling the requirements for specific functionality isn't a hack.

Within this use case, I don't think an OID is required for any specific functionality per se, I think it's because an assumption has been made in the the FeatureLayer class code that an OID will be there, therefore I'd be employing at least a 'workaround', perhaps 'hack' is too strong a term, but it's my (subjective) opinion!

We don't explicitly document that an object ID is required

Well, I agree that conceptually one shouldn't be always required but it appears the developer(s) thought otherwise.

but it is implied in that the main use case for feature layers is using data from ArcGIS Server.

Non sequitur - I disagree that that implies that an OID is mandatory, in fact I interpret that to mean if you can publish data via AGS then you can simply point the FeatureLayer at the layer within that AGS service and it will work, the two components are fully compatible with each other.

I think many of your other customers would view this the same way.

As you've outlined, it's possible to publish data with AGS that doesn't have an object ID.

Absolutely, with no warnings etc. in fact the only warnings I see are in ArcMap when it tells me there's some restricted functionality to do with selections etc. since I don't want or need to do any selections this appears irrelevant to my usage.

We'll update the docs.

I think it'd be a pity to take that approach, why not just enhance the FeatureLayer a little so it can cope with data that don't have an OID?  (seems odd that all the other layer types can cope and this one can't, maybe it needs another 'mode' like 'MODE_RENDERONLY'!)

AGS returns all the features in the JSON response just fine without the use of an OID, I would expect the FeatureLayer to at least be able to render them.

This is digressing a little, but for 'fun' I've overridden ('hacked' I suppose!) the _drawFeatures method in the _OnDemandMode class so that it submits the loop index as the OID argument to the _addFeatureIIf method if the OID is undefined, that way the _addFeatureIIf method doesn't use a 'value' of undefined as the key to the featureMap - this bit explains why people only see one feature rendered in this scenario i.e. the same key value of undefined is attributed to every feature therefore in the _addFeatureIIf it looks like all subsequent features (after the first one as been added) have already been added to the map.

I found more topics than this the other day, will post the links if I find them again:

With this in place all my features are rendered, but I have no idea what effects, probably negative, this will have on other functionality within the layer, it's far too risky to use for real, unless someeone can tell me otherwise!

I'd rather try to do things in a standard way...which probably means introducing a surrogate key, the thing is the underlying data are temporal, dynamic, rotating and vary in volume of throughput, I realise it will take a long time to 'run out' of numbers but it's still conceptually 'dirty'!  (yes, I can put something in place to re-seed the identity when it hits the limit etc. etc.)

Back to the matter at hand...
A couple more questions:  what's the mode for your feature layer? What kind of things are you wanting to do client side?

1)  At present I don't specify a mode so it should default to MODE_ONDEMAND
2)  Simple stuff really, I need to trigger some functionality as each feature is added to the layer, and that bit works fine....provided all the features render!

Thanks for your help 🙂
0 Kudos
__Rich_
Deactivated User
OK, there doesn't appear to be any quick way around this, not today anyway.......added identity column to underlying table...grrrrrrrrr 😉  (this doesn't mean I don't think a future enhancement to the FeatureLayer should be forgotten!)

Now that I've done that, I've got a couple of questions:


  1. Is there a way to get ArcMap/AGS/FeatureLayer to automatically recognise which column (field) to use as the OID?  (e.g. so I don't have to pass objectIdField:"oid" in the FeatureLayer constructor)

  2. I would have thought that now it has a unique identifier for each feature calling refresh() on the layer wouldn't cause all features to be removed then redrawn, e.g. I'd have thought that only 'new' features i.e. with an OID not known to the client would be drawn and likewise the only features removed would be ones that are no longer in the JSON returned from AGS.  I'm seeing ALL features being removed and then added which isn't very efficient!


Thanks.
0 Kudos
derekswingley1
Deactivated User
The term surrogate key is new to me. Somehow I've managed to not come across that one over the years...or I've just forgotten it :).

For the present and near future, the feature layer will continue to require an object id. As you've found by exploring the inner workings of the layer, OIDs are used to keep track of features internally. If you want to go further, the next thing to do would be to log an enhancement request through support.

If you can publish your layer such that your key field has a type of esriFieldTypeOID, the feature layer will automatically pick that up. Otherwise, you need to manually specify your key field. As far as how to publish a map service that uses an XY event layer and has a field with a type of object ID, I'm not sure how to do that. I hate to pass the buck, but you might be better off asking that question in the general server forum:  http://forums.arcgis.com/forums/8-ArcGIS-Server-General
0 Kudos
derekswingley1
Deactivated User

I would have thought that now it has a unique identifier for each feature calling refresh() on the layer wouldn't cause all features to be removed then redrawn, e.g. I'd have thought that only 'new' features i.e. with an OID not known to the client would be drawn and likewise the only features removed would be ones that are no longer in the JSON returned from AGS.  I'm seeing ALL features being removed and then added which isn't very efficient!


That's as designed:  http://help.arcgis.com/en/webapi/javascript/arcgis/help/jsapi/featurelayer.htm#refresh

What if features have been modified since they were originally retrieved?
0 Kudos
__Rich_
Deactivated User
That's as designed:  http://help.arcgis.com/en/webapi/javascript/arcgis/help/jsapi/featurelayer.htm#refresh

What if features have been modified since they were originally retrieved?

"The feature layer requeries all the features in the service, except the selected features, and updates itself."

Then I'd update those features rather than removing and re-adding them...that's what I would have thought happens based on the above.  If ALL the features are going to be removed then re-added regardless then what's the point of the OID in this scenario?

It also does a remove/add when zooming/panning to an existing feature, is that expected?

The crux of the issue is this:- what I really want is to know when a new feature has been added within the current extent and I can't see which of the public events would yield that information, is there a way to do this without having to initiate my own separate query/processing?   (also knowing in future which have been removed/updated would be useful!)

Thanks 🙂
0 Kudos
derekswingley1
Deactivated User

Then I'd update those features rather than removing and re-adding them...that's what I would have thought happens based on the above.  If ALL the features are going to be removed then re-added regardless then what's the point of the OID in this scenario?

If you're using a layer from a map service as a feature layer, only new features are added. If your feature layer points to a feature service, all features are removed then added. Is the source for your feature layer a layer from a map service or a feature service?


It also does a remove/add when zooming/panning to an existing feature, is that expected?

Yes, this is expected because features are generalized on a per zoom level basis. See the "Feature Generalization" section of Feature Layer Best Practices.


The crux of the issue is this:- what I really want is to know when a new feature has been added within the current extent and I can't see which of the public events would yield that information, is there a way to do this without having to initiate my own separate query/processing?   (also knowing in future which have been removed/updated would be useful!)

I should have asked this before...can you expand on this workflow a bit? As you've found out, we don't provide events that fire for the specific addition of new features outside of events related to aplyEdits.
0 Kudos
__Rich_
Deactivated User
Thanks for the response, answers below...

If you're using a layer from a map service as a feature layer, only new features are added. If your feature layer points to a feature service, all features are removed then added. Is the source for your feature layer a layer from a map service or a feature service?

It's a map service....but I will double check that ALL features are definitely being redrawn and that's not just my imagination!

Yes, this is expected because features are generalized on a per zoom level basis. See the "Feature Generalization" section of Feature Layer Best Practices.

OK, but because all the features in this particular layer are points I didn't think this would apply?  (I'll have a play with turning the auto generalise stuff off)

I should have asked this before...can you expand on this workflow a bit? As you've found out, we don't provide events that fire for the specific addition of new features outside of events related to aplyEdits.

OK, time-series of dynamic point features being inserted ad-hoc by an external process into a database, I'd like to know (on the client-side) that new features (and how many) have been added since the last refresh.  The way it's working at present is acceptable but it'd be much better to be able to distinguish between new and existing (temporally) features without providing my own state maintenance.  If it can't be done 'out-the-box' then fair enough, I just want to make sure I haven't missed something in the API that I could hook into and/or some settings that would change the behaviour to provide this level of detail.

If it doesn't exist then it'd be nice to see it in a future version 🙂
0 Kudos
derekswingley1
Deactivated User

OK, time-series of dynamic point features being inserted ad-hoc by an external process into a database, I'd like to know (on the client-side) that new features (and how many) have been added since the last refresh.  The way it's working at present is acceptable but it'd be much better to be able to distinguish between new and existing (temporally) features without providing my own state maintenance.  If it can't be done 'out-the-box' then fair enough, I just want to make sure I haven't missed something in the API that I could hook into and/or some settings that would change the behaviour to provide this level of detail.


You're not missing anything, the feature layer doesn't provide the events you're describing. If you don't want to build this out yourself, you might want to look into tracking server:  http://www.esri.com/software/arcgis/tracking-server/index.html
0 Kudos
__Rich_
Deactivated User
You're not missing anything, the feature layer doesn't provide the events you're describing. If you don't want to build this out yourself, you might want to look into tracking server:  http://www.esri.com/software/arcgis/tracking-server/index.html

That's a pity, especially as all the information required to raise the appropriate events is available (and used) within the existing class (feature collection, OIDs etc.) any chance this might make it into a future version?
0 Kudos