1
votes

I am putting together a store finder which works on a radius from a postal code. I have done this many times using standard Queries and QoQs, but now trying to put one together using cf9 ORM... but seemed to have reached the limit of my capabilities with the last bit.

I am pulling out an entity and processing it. At the end, I need to:

a. Remove a record if it doesn't meet a certain criteria (distance is greater than specified by user)

OR b. Add a new property to the record to store the distance.

So at the end, all I want in my entity are those stores that are within the range specified by the user, with each record containing the calculated distance.

Best way to see what I am trying to do is to view the full function

Any suggestions greatly appreciated!!

public function getByPostcodeRadius(required postcode="", 
                                        required radius=""){

        //set some initial vals
        rs = {};
        geo = New _com.util.geo().init(); 
        local.postcodeGeo = geo.getGeoCode("#arguments.postcode#, Australia");
        local.nearbyStores = "";
        local.returnStores = {};

        //load stores
        local.stores = entityload("stores");

        //loop over all stores and return list of stores inside radius
        for(i=1; i <= ArrayLen(local.stores); i++){

            store = {};
            store.id = local.stores[i].getID();
            store.geoCode = local.stores[i].getGeoCode();
            store.Lat = ListgetAt(store.geoCode,1);
            store.Lng = ListgetAt(store.geoCode,2);

            distance = geo.getDistanceByGeocode(local.postcodeGeo.Lat,local.postcodeGeo.Lng,store.Lat,store.Lng);


            //************************
            //HERE IS WHERE I AM STUCK.

            if (distance LT arguments.radius){

                //here I need to add a property 'distance' and set it's value
                local.stores[i].distance = distance; // this adds it to the object, but not with the PROPERTIES

            } else {

                // here i need to remove the store from the object as it's distance was greater than the one passed in
                arrayDeleteAt(local.stores,i); //this clearly isn't working, as positions are changing with each loop over

            }

        }

        return local.stores;
}
2

2 Answers

2
votes

If you delete an object from an array it will mess up your loop.

Try either looping backwards:

var i = arrayLen( local.stores );
for ( i; i == 0; i-- )

Or looping like this

for ( var local.store in local.stores )

(That's rough code and may need some tweaks)

1
votes

I'd approach this from a different angle:

1) Instead of deleting from the array of all stores those that don't match, I'd build an array of those that do and return that.

2) If the distance is specific to each query and not a property of the store object, then I wouldn't try adding it to the store, but just "associate" it with the specific data I'm returning for this search.

Putting to the 2 together, I'd return an array of structs containing the store object and its distance from the requested postcode. (You could just return a single struct of the store object and distance, with the store ID as key, but I prefer working with arrays.)

Here's how I'd code it (not tested because I don't have your geo class or entity code):

public array function getByPostcodeRadius(required postcode="", required radius=""){
hint="I return an array of structs each containing a store object within the requested radius and its distance from the requested post code"
// Geo settings
local.geo = New _com.util.geo().init(); 
local.postcodeGeo = local.geo.getGeoCode("#arguments.postcode#, Australia");
// initialise the array of structs to return, which will contain stores within the requested radius and their distance from the postcode
local.nearbyStores = [];
//load all stores
local.stores = entityload("stores");
//loop over all stores and add those inside the radius to the return array with their distance
for( var storeObject in local.stores ){
    // determine the lat-lng for this store
    local.storeLat = ListgetAt(storeObject.getGeoCode(),1);
    local.storeLng = ListgetAt(storeObject.getGeoCode(),2);
    // get the distance from the requested postcode
    local.distance = local.geo.getDistanceByGeocode(local.postcodeGeo.Lat,local.postcodeGeo.Lng,local.storeLat,local.storeLong);
    if (local.distance LT arguments.radius){
        // create a struct of the store object and its distance and add to the nearby stores array
        local.thisStore =   {
            store   =   storeObject
            ,distance   =   local.distance
        };
        ArrayAppend( local.nearbyStores,local.thisStore );
    }
}
return local.nearbyStores;
}