0

I'm trying out the spatial search in Solr. What I did was to stop the service, then updated the schema.xml file for collection1 to include the following:

<fieldType name="location" class="solr.LatLonType" subFieldSuffix="_coordinate"/>
<dynamicField name="*_coordinate"  type="tdouble" indexed="true"  stored="true"/>

<field name="location" type="location" indexed="true" stored="true"/>
<field name="location_0_coordinate" type="double" indexed="true" stored="true"/>
<field name="location_1_coordinate" type="double" indexed="true" stored="true"/>

And then I started the service again to update the document in Solr:

$local_select = 'http://localhost:8080/solr/select?q=ss_type:(business%20OR%20user%20OR%20blog)&wt=json';

$url = $local_select;
$data = file_get_contents($url);
$r_data = json_decode($data, true);

$docs = $r_data['response']['docs'];



if(!empty($docs)){
    foreach($docs as $doc){


        if(!empty($doc['tm_field_business_address:postal_code'][0])){

            $postal_code = urlencode($doc['tm_field_business_address:postal_code'][0]);

            $api = 'http://maps.googleapis.com/maps/api/geocode/json?address=' .  $postal_code . '&sensor=false';
            $api_results = file_get_contents($api);
            $data = json_decode($api_results, true);

            if($data['status'] == 'OK'){
                $location = $data['results'][0]['geometry']['location'];

                unset($doc['_version_']);

                $doc['location_0_coordinate'] = $location['lat'];
                $doc['location_1_coordinate'] = $location['lng'];
                $new_docs[] =  $doc;
            }
        }
    }
}




$local_update = 'http://localhost:8080/solr/update/json';
$local_commit = 'http://localhost:8080/solr/update?commit=true';

//update the solr index
if(!empty($new_docs)){
    $json_doc = json_encode($new_docs);

    $curl = curl_init();

    curl_setopt_array($curl, array(
        CURLOPT_RETURNTRANSFER => 1,
        CURLOPT_HTTPHEADER => array("Content-type:application/json"),
        CURLOPT_URL => $local_update,
        CURLOPT_POST => 1,
        CURLOPT_POSTFIELDS => $json_doc,
    ));

    $update_response = curl_exec($curl);
    curl_close($curl);


    //commit the changes
    $curl = curl_init();
    curl_setopt_array($curl, array(
        CURLOPT_URL => $local_commit
    ));


    $commit_response = curl_exec($curl);
}

The curl responses were both ok and when I checked the results using this query:

http://localhost:8080/solr/select?q=ss_type:(business%20OR%20user%20OR%20blog)

It returned the results:

<double name="location_0_coordinate">49.9641523</double>
<double name="location_1_coordinate">10.1378365</double>

Now my problem is have I really set this up properly? And if yes, what will be the query that I can use to check if its really returning something once I use a spatial query like the one below:

http://localhost:8080/solr/select/?q=ss_type:(business%20OR%20user%20OR%20blog)&fq={!geofilt}&sfield=location&pt=49.9641523,10.1378365&d=0

My main problem here is that I don't really know what to supply for the reference point in order for it to return a record which already exists in the Solr index.

So for example if I have the following coordinates in the index:

49.9641523,10.1378365

What will be the spatial query that would return the specific record which has that coordinate. I tried to use d=0 but nothing is returned:

<response>
<result name="response" numFound="0" start="0"/>
</response>

Any ideas? Thanks in advance.

user225269
  • 10,743
  • 69
  • 174
  • 251

2 Answers2

1

You should store the latitude and longitude in the same field, separated by comma. E.g. <latitude>,<longitude>

Field type should be location.

<dynamicField name="*_coordinate"  type="location" indexed="true" stored="true"/>

Pass in the following parameters in your query:

pt - The Point to use as the center of the filter. Specified as a comma separated list of doubles. It is lat,lon.

d - The distance (in KM) from the point to the outer edge of whatever is being used to filter on

sfield - The field with coordinate.

The following sample gespatial query will return all locations within 5km of the specified point 49.9641523, 10.1378365

http://localhost:8080/solr/select?q=*:*&fq={!geofilt}&pt=49.9641523,10.1378365&sfield=location_coordinate&d=5
Stanley
  • 5,057
  • 4
  • 34
  • 44
  • so something like: `$doc['location_coordinate'] = $location['lat'] . ',' . $location['lng']` ? – user225269 Jun 20 '13 at 04:49
  • I'm getting an error if I do the one above: `Error adding field 'location_coordinate'='51.3223777,-0.1358427' msg=For input string: \"51.3223777,-0.1358427\"","code":400}}` – user225269 Jun 20 '13 at 04:52
  • The field type has to be `location` – Stanley Jun 20 '13 at 06:41
  • I just want to point out that there is a SpatialRecursivePrefixTreeFieldType (assigned to name "location_rpt" in the default schema). It's much faster than LatLonType, particularly if you have a ton of data. But I still recommend LatLonType for spatial sorting/relevancy with geodist() if you need that. Both can be used. – David Smiley Jun 20 '13 at 13:43
0

OK I figured it out, there's actually a default dynamic field in the schema.xml file that allows you to store coordinates, it has a field type of location. so even if I have no access to the schema.xml file I can still define it like this:

$doc['locm_store'] = $location['lat'] . ',' . $location['lng'];

The equivalent in an xml document would be:

<field name="locm_store">123,456</store>

Where 123 is the latitude and 456 is the longitude.

user225269
  • 10,743
  • 69
  • 174
  • 251