Forum

Thread tagged as: Question, Problem, Runway

Filter by Latitude and Longitude (Part 2)

Me again,

Following on from https://forum.grabaperch.com/forum/10-01-2015-filter-by-latitude-and-longitude

After getting this to the client and having them add a nice amount of data, I've run in to some odd behaviour when filtering by map_lat and map_lng. For some reason I am getting an or match rather than and no matter what I do. I'm not sure if this is related to collections or the map field type.

I've also just noticed that items that DO match both latitude and longitude, don't actually get pulled through to the results.

if ($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_POST)) {

    $usr_input = isset($_POST['loc']) && !empty($_POST['loc']) ? htmlspecialchars($_POST['loc']) : '';
    $usr_dist = (isset($_POST['dist']) && is_numeric($_POST['dist'])) ? (int) $_POST['dist'] : 10;
    perch_layout('locations_form',[
        'page' => PerchSystem::get_page(),
        'input' => $usr_input,
        'distance' => $usr_dist
    ]);

    //stuff like getDistance, getDueCoords and lookup all in here.
    perch_layout('locations_functions');

    $usr_loc = lookup($usr_input);
    if (isset($usr_loc['error'])) {

        // TODO: switch case for error messages.
        echo "Error";

    } else {

        $north = getDueCoords($usr_loc['latitude'], $usr_loc['longitude'], 0, $usr_dist);
        $south = getDueCoords($usr_loc['latitude'], $usr_loc['longitude'], 180, $usr_dist);
        $east = getDueCoords($usr_loc['latitude'], $usr_loc['longitude'], 90, $usr_dist);
        $west = getDueCoords($usr_loc['latitude'], $usr_loc['longitude'], 270, $usr_dist);
        echo "<!-- Lat:".$north['lat'].' to '.$south['lat']." Lng:".$west['lng'].' to '.$east['lng']." Input: ".$usr_loc['country']." -->";

        PerchSystem::set_vars([
            'usr_loc' => $usr_input,
            'usr_dist' => $usr_dist.' miles'
        ]);
        $stuff = perch_collection('Locations', [
            'filter' => [
                [
                    'filter' => 'country',
                    'match' => 'contains',
                    'value' => $usr_loc['country'],
                ],[
                    'filter' => 'map_lat',
                    'match' => 'between',
                    'value' => $south['lat'].','.$north['lat'],
                ],[
                    'filter' => 'map_lng',
                    'match' => 'between',
                    'value' => $west['lng'].','.$east['lng'],
                ]
            ],
            'each' => function($item) {
                $the_loc = $GLOBALS['usr_loc'];
                $lat_min = $GLOBALS['south']['lat'];
                $lat_max = $GLOBALS['north']['lat'];
                $lng_min = $GLOBALS['west']['lng'];
                $lng_max = $GLOBALS['east']['lng'];
                $item_lat = $item['map']['lat'];
                $item_lng = $item['map']['lng'];
                if (!($item_lng > $lng_min && $item_lng < $lng_max)) {
                    $item['longitude'] = "Out of range";
                }
                if (!($item_lat > $lat_min && $item_lat < $lat_max)) {
                    $item['latitude'] = "Out of range";
                }
                $item['distance'] = getDistance($the_loc['latitude'], $the_loc['longitude'], $item['map']['lat'], $item['map']['lng']).' miles';
                $item['start'] = $the_loc['latitude'].','.$the_loc['longitude'];
                $item['destination'] = $item['map']['lat'].','.$item['map']['lng'];
                return $item;
            },
            'skip-template' => true,
            'raw' => true
        ],true);

        var_dump($stuff);
    }

}

Mark Greenwood

Mark Greenwood 0 points

  • 6 years ago
Drew McLellan

Drew McLellan 2638 points
Perch Support

Matches should be and by default, but try setting it:

 'match'=>'and'

Hi Drew,

Thanks for that, I've tried it but to no avail. It seems odd that the ones that should be an and match aren't getting through, yet the or ones are.

Could it be related to the hidden fields being part of another field? So if it finds one match for the map, it toggles it as a match, finds two and it's a dupe so gets removed. Clutching at straws there, obviously.

Drew McLellan

Drew McLellan 2638 points
Perch Support

Do map_lat and map_lng appear correctly in the collection index table?

Yes, they are top level array elements on the item, here is an example from var_dump (I edited out the admin_html and the bottom four keys are added via each.):

[0]=>
  array(16) {
    ["_id"]=>
    string(3) "175"
    ["name"]=>
    string(27) "Salisbury District Hospital"
    ["_title"]=>
    string(27) "Salisbury District Hospital"
    ["map"]=>
    array(11) {
      ["adr"]=>
      string(36) "Salisbury District Hospital, SP2 8BJ"
      ["_title"]=>
      string(36) "Salisbury District Hospital, SP2 8BJ"
      ["_default"]=>
      string(36) "Salisbury District Hospital, SP2 8BJ"
      ["lat"]=>
      string(17) "51.04549910000001"
      ["lng"]=>
      string(19) "-1.7886934000000565"
      ["clat"]=>
      string(17) "51.04549910000001"
      ["clng"]=>
      string(19) "-1.7886934000000565"
      ["zoom"]=>
      string(2) "15"
      ["type"]=>
      string(3) "map"
      ["admin_html"]=>
      string(313) "..."
      ["html"]=>
      string(788) "Salisbury District Hospital, SP2 8BJ"
    }
    ["map_lat"]=>
    string(17) "51.04549910000001"
    ["map_lng"]=>
    string(19) "-1.7886934000000565"
    ["address"]=>
    string(43) "Odstock Road
Salisbury
Wiltshire
SP2 8BJ"
    ["info"]=>
    NULL
    ["country"]=>
    string(14) "United Kingdom"
    ["phone"]=>
    NULL
    ["website"]=>
    NULL
    ["_sortvalue"]=>
    string(4) "1005"
    ["latitude"]=>
    string(12) "Out of range"
    ["distance"]=>
    string(12) "179.67 miles"
    ["start"]=>
    string(19) "53.645792,-1.785035"
    ["destination"]=>
    string(37) "51.04549910000001,-1.7886934000000565"
  }

I should add the search for this had the area limits of Lat:53.573506665 to 53.718077335 Lng:-1.90697876335 to -1.66309123665

Sorry, I missed that you meant the database table but the indexKeys map_lat and map_lng are indeed there, too along with the corresponding indexValues. However, I've noticed that there are two of each for each item. Investigating now.

Drew McLellan

Drew McLellan 2638 points
Perch Support

You'll find multiple versions in there, which is ok. I just wanted to check that the values that we thought were being indexed actually were.

As well as the versions there are duplicates of the lat and lng records, within each version. I've deleted the hidden fields from the template and re-saved a couple of locations and the matches I wasn't getting through before now appear along with the additional matches I don't want. So, this is progress, I just need to re-save 100 items to see if it gives me better results all round.

I've taken a screen shot here, can you see the dups causing an issue (about 10 rows up from bottom and 6 rows from top, ignore the slug experiment)?

It appears that the duplicate fields I had put in there were the issue, which is odd as it originally didn't seem to work until I had put them in. So I'm a bit confused but everything seems to be in order now that I re-saved every item in the collection to get rid of the extra fields.

Thanks for pointing me in the right direction!

Drew McLellan

Drew McLellan 2638 points
Perch Support

Great!