Factual PHP Driver

We are pleased to report the availability of the official PHP driver for the Factual API. This driver wraps our Read, Crosswalk, Resolve, and Schema APIs, providing five-line access to our 55 million global places and other structured data.

Examples

Getting Started:

First, get an API key from Factual. Add your oauth key and secret to the constructor:

	require_once('Factual.php');
	$factual = new Factual("yourOauthKey","yourOauthSecret");

Follow with syntax specific to the selected API:

Read [docs]

The driver provides the same powerful abilities to query, filter, order, and sort as provided via the REST API:

	//Free text query
	$query = new FactualQuery;
	$query->search("Sushi Santa Monica");  //searches across numerous fields
	$query->field("country")->equal("US"); //limit results to the US
	$res = $factual->fetch("places", $query);
	print_r($res->getData());	
 
	//Search near a point
	$query = new FactualQuery;
	$query->within(new FactualCircle(34.06018, -118.41835, 5000)); //5k meter radius
	$query->limit(10); //only get ten results
	$query->sortAsc("\$distance"); //order results by distance
	$res = $factual->fetch("places", $query);
	print_r($res->getData());

We also allow for nested conditions and the complete range of parametric operators. If we have it, you can find it.

Resolve [docs]

Provided to meet all of your entity enrichment and matching needs:

	//Find a match at a specific lon/lat
	$query = new ResolveQuery();
	$query->add("name", "Buena Vista Cigar Club");
	$query->add("latitude", 34.06);
	$query->add("longitude", -118.40);
	$res = $factual->fetch("places", $query);
	print_r($res->getData());

Crosswalk [docs]

Find third-party identifiers and URLs:

	//Get all crosswalks for a specific Factual ID
	$query = new CrosswalkQuery();
	$query->factualId("97598010-433f-4946-8fd5-4a6dd1639d77");
	$res = $factual->fetch("places", $query);
	print_r($res->getData());

Schema [docs]

Table introspection:

	//Get the schema for the Global Places table
	$res = $factual->schema("places");
	print_r($res->getColumnSchemas());
	exit;

Geocoding

And we’ve thrown in some cheeky geocoding:

	//geocode (convert an address to a longitude and latitude)
	$res = $factual->geocode("425 Sherman Ave, Palo Alto, CA, USA");
	print_r($res);
 
	//reverse geocode (convert an address to a longitude and latitude)
	$res = $factual->reverseGeocode(-122.143895,37.425674);
	print_r($res);

Factual does not provide a geocoding service, so these use a third-party; we’ve included these methods as convenient, if simple, hooks. Like the MPAA’s claims that online piracy is ruining America’s economy, they are unsupported.

Get It Here

The driver is open source and can be downloaded from https://github.com/Factual/factual-php-driver.  Example code and detailed commentary are provided in the PHP Driver Readme. Driver support and feature requests can be pinged to the Factual Developer Group. Rockin.

-Tyler Bell
Director of Product

Factual Support for SimpleGeo Customers

Earlier today Urban Airship let their customers know that they will start winding down the existing SimpleGeo Places service over the next couple of months, with a target service end date of March 31, 2012. Urban Airship will be focusing on integrating location and context services into their push messaging platform. We have good news to add here: since June 2011, Factual has been providing its Places data to SimpleGeo and developers currently using SimpleGeo’s API for Places Data can seamlessly migrate to Factual’s API to get access to the same data.

We have been working with Urban to make it easy for you. Our how-to guide will walk you through the steps for migration. If you have any questions or need help, support is available at our developer group.

We look forward to serving you!

Vikas Gupta
Product Marketing Manager

Crosswalk the Web with Java and Factual

Factual is pleased to announce the release of a new Java driver for our API. The driver supports Factual’s API features, including Crosswalk, Resolve, and geo location functionality around the Factual Places API.

We put a priority on making this driver easy to use. It lets you focus on building your Factual queries and using the results in Java. It handles details like OAuth, url encoding, and JSON marshaling so you don’t have to.

The driver is hosted on Maven Central, so if you’re using Maven you can install it in your project just by adding this to your pom file:

<dependency>
  <groupId>com.factual</groupId>
  <artifactId>factual-java-driver</artifactId>
  <version>1.0</version>
</dependency>

Once you have the driver installed in your Java project, here’s how you create an authenticated handle to Factual:

Factual factual = new Factual("YOUR_API_KEY", "YOUR_API_SECRET");

The driver provides a fluent interface to build your Factual queries. For example, here’s how you build a query to use full text search and a geo filter to find cafes within 5,000 meters of your location, using your latitude and longitude:

Query q = new Query()
  .search("cafe")
  .within(new Circle(34.06018, -118.41835, 5000));

There’s also fluent support for detailed results filtering. To illustrate a bit of this, here’s how you build a query to return the name and address of cafes within 5,000 meters of a lat/long, while limiting to a specific zip code, category, and size of returned results:

Query q = new Query()
  .only("name", "address")
  .search("cafe")
  .within(new Circle(34.06018, -118.41835, 5000))
  .field("postcode").equal("90067")
  .field("category").equal("Food & Beverage")
  .limit(25);

We’re also experimenting with built-in support for the venerable Data Science Toolkit. This gives you an easy way to lookup location coordinates based on address information. For example, you could find Factual’s latitude and longitude by using the text “1801 avenue of the stars, century city, ca”:

Coord coord = new DataScienceToolkit()
  .streetToCoord("1801 avenue of the stars, century city, ca");

This support is built in to the driver’s fluid interface for querying on Factual’s Places data. Here’s an example of finding cigar shops within 5,000 meters of an address:

ReadResponse cigars = factual.fetch("places", new Query()
  .search("cigars")
  .near("1801 avenue of the stars, century city, ca", 5000));

Crosswalk The Web

The driver has full support for Crosswalk, which makes it super easy for you to translate how Place entities are represented by 3rd party APIs and websites.

To illustrate, let’s take a look at the first record returned from our cigar search:

System.out.println(cigars.getJson());

That looks like:

{
  "version" : 3,
  "status"  : "ok",
  "response":
  {
    "data":
    [{
       "factual_id": "5e2c36e4-aeb8-49b8-8652-defcd8ad5808",
       "name"      : "Buena Vista Cigar Club",
       "address"   : "9715 Santa Monica Blvd",
       "locality"  : "Beverly Hills",
       "region"    : "CA",
       "country"   : "US",
       "postcode"  : "90210",
       "tel"       : "(310) 273-8100",
       "category"  : "Shopping > Tobacco Shops",
       "website"   : "http://www.buenavistacigarclub.com/",
       "latitude"  : 34.068735,
       "longitude" : -118.407808,
       "status"    : "1",
       "$distance" : 1280.624
     },
     ...

That’s some tasty data about the Buena Vista Cigar Club, including its unique Factual ID. Next, by using Crosswalk and the Factual ID, we can get links out to other authorities for this entity:

CrosswalkResponse crosswalks = factual.fetch("places",
  new CrosswalkQuery().factualId("5e2c36e4-aeb8-49b8-8652-defcd8ad5808"));
 
System.out.println(crosswalks.getJson());

That’s going to look like:

{
  "version" : 3,
  "status"  : "ok",
  "response":
  {
    "data":
    [
      {
        "factual_id"  : "5e2c36e4-aeb8-49b8-8652-defcd8ad5808",
        "namespace"   : "facebook",
        "namespace_id": "141751493637",
        "url"         : "http://www.facebook.com/pages/Buena-Vista-Cigar-Club/141751493637"
      },
      {
        "factual_id"  : "5e2c36e4-aeb8-49b8-8652-defcd8ad5808",
        "namespace"   : "yelp",
        "namespace_id": "",
        "url"         : "http://www.yelp.com/biz/buena-vista-cigar-club-beverly-hills"
      },
      {
        "factual_id"  : "5e2c36e4-aeb8-49b8-8652-defcd8ad5808",
        "namespace"   : "yellowpages",
        "namespace_id": "",
        "url"         : "http://www.yellowpages.com/beverly-hills-ca/mip/buena-vista-cigar-club-12303827"
      },
      ...

Each record represents a specific Crosswalk authority, or what we call a “namespace”, e.g. “yelp”, “facebook”, “yellowpages”, and so on.

Attributes include the namespace’s link and ID for the entity. E.g., the Yelp link for the Buena Vista Cigar Club is http://www.yelp.com/biz/buena-vista-cigar-club-beverly-hills, and the Yelp ID is "u_3ywlxdwq--WxxOO_3TVg".

Crosswalk lets you go the other direction as well. Say all you have is the Facebook ID for the Buena Vista Cigar Club. You can do this…

System.out.println(
  factual.fetch("places", new CrosswalkQuery()
    .namespace("facebook")
    .namespaceId("141751493637")
    .only("facebook")
  ).getJson());

That looks like…

{
  "version" : 3,
  "status"  : "ok",
  "response":
  {
    "data":
    [
      {
        "factual_id"  : "5e2c36e4-aeb8-49b8-8652-defcd8ad5808",
        "namespace"   : "facebook",
        "namespace_id": "141751493637",
        "url"         : "http://www.facebook.com/pages/Buena-Vista-Cigar-Club/141751493637"}
    ],
    "included_rows"  : 1,
    "total_row_count": 1
  }
}

… which includes the Factual ID of the entity. With that you can continue querying Factual’s system for whatever you want to know about the entity.

Factual has support for 30+ namespaces. You can see the detailed list here.

You can use Crosswalk to relate and aggregate content across web authorities, and mashup the best content from each.

Resolve

Resolve lets you start with incomplete data you may have for an entity, and get out the full entity data, assuming Factual is able to make a high confidence match.

For example, say you know the name of a place and some imprecise location. The Java driver lets you use Resolve to get a single, high-quality match, like this:

System.out.println(
  factual.resolve(
    new ResolveQuery()
      .add("name", "Buena Vista")
      .add("latitude", 34.06)
      .add("longitude", -118.40)

This shows you Factual’s full record for the resolved entity as a Map, including its Factual ID:

{
  name      = Buena Vista Cigar Club,
  region    = CA,
  status    = 1,
  tel       = (310) 273-8100,
  postcode  = 90210,
  country   = US,
  category  = Shopping &gt; Tobacco Shops,
  resolved  = false,
  address   = 9715 Santa Monica Blvd,
  locality  = Beverly Hills,
  longitude = -118.407808,
  latitude  = 34.068735,
  similarity= 0.7142857142857143,
  factual_id= 5e2c36e4-aeb8-49b8-8652-defcd8ad5808
}

Conclusion

We hope you’ll find new and interesting uses for Factual, including Crosswalk and Resolve. If you end up releasing something interesting, please let us know so we can give you a shout-out!

Complete docs on how to install and use the Java driver are here. The driver itself is open source. The test suite includes integration tests as well as simple demos to illustrate usage. If you have any questions or suggestions, we hope you’ll contact us through the driver’s github project.

Factual’s service is currently in Beta, and you can obtain an API key here.

P.S.: You should follow me on Twitter here.

A Globally Transparent API

We’ve been globalizing our services over the last few months at Factual to better serve the needs of a borderless Internet: all global place data is now accessible via a single API endpoint, and we’ve added two new countries, China and Canada. With this announcement, Factual is the only service in the world where developers can access structured information from 55+ million places globally via a single API gateway. We have made it easy for any developer to find all sushi restaurants in the world, all Starbucks in North America, and all service stations in Europe.

Global API

Previously at Factual, we divided our place data by country: while easy to manage, developers needed to know in advance what table to query. Now, all countries are centrally located and can be queried simultaneously. Search and browse the results here. All data is represented in the common local language: you can search for places in Russia using Cyrillic, in Egypt using Arabic, and Israel using Hebrew. All countries share a common global schema to simplify developer access and data management. All together it is a big database, but we keep it fast: you can read more on this blog about our technology stack. We’ve also just today launched deep attributes for over 800k restaurants in the US.

New Countries

Today we’re also introducing two new countries to our global coverage of the world’s places:

  • Canada: 1.8 million entities
  • China (beta): 9.8 million entities

This brings our running total to 55 million places in 47 countries, not that we’re counting.

Learning More

Tyler Bell
Factual Product Bod

Factual Restaurants

When looking for a good restaurant, it’s not enough to just know its address or phone number. You also want to know: Is it open? Can I bring my 4-year old? Will it break my wallet? Do others like it? BYOB? Our Restaurants dataset can now help your users answer these questions and more, supporting use cases such as ‘find me a nice place for dinner in NYC with valet parking and a full bar’. As of today, we offer 43 additional attributes including cuisine, ratings, and hours for the 800k+ restaurants and casual eateries found in our US Places table.

Our approach to deep attributes is designed to enhance discovery, exploration and serendipity. If you are developing apps that require Food & Drink data, look no further than this table. (If you are looking for Global Places, we’ve just announced new availability here).

The 43 additional attributes include:

  • price, cuisine, rating, hours
  • alcohol: bar, beer & wine, BYOB
  • good for: kids, groups
  • parking: on-street, valet, garage, validated
  • meal types: breakfast, lunch, dinner, delivery, take-out, catering
  • meal options: vegetarian, vegan, low-fat, gluten-free, healthy, organic
  • cash only
  • wheelchair accessibility
  • dining experience: takes reservations, wifi, smoking, attire, outdoor seating, private room
  • about the venue: year founded, owner

Learning More

Querying Restaurants

As a developer, you can use the V3 API which employs the same filter context you are familiar with (these examples are formatted for readability — remember to URL-encode your request values):

http://api.v3.factual.com/t/restaurants-us/read?
      filters={
          "locality":"New York",
          "parking":true,
          "alcohol":true,
          "meal_dinner":true
      }&
      KEY=[your key]

This query returns the first fifty restaurants in New York with parking that serve alcohol with dinner (use the offset parameter to pull the next set). If that’s too many, let’s select only places with valet parking and a full bar:

  http://api.v3.factual.com/t/restaurants-us/read?
      filters={
         "locality":"New York",
         "parking_valet":true,
         "alcohol_bar":true,
         "meal_dinner":true
     }&
      KEY=[your key]

These attributes are also indexed as tags, which enable full text search against them. Developers may find it easier to just create ad hoc queries, rather than querying against specific attributes:

   http://api.v3.factual.com/t/restaurants-us/read?
      q=dinner+valet+bar+New York&
      KEY=[your key]

This query produces almost the identical results to the one above, with a few extra lines because words can appear in other than the expected field – such as “New York Avenue”. Here we do a combination of filters and free text search:

 http://api.v3.factual.com/t/restaurants-us/read?
      q=dinner+valet+bar&
      filters={
         "locality":"New York"
      }&
      KEY=[your key]

Now we have a precise location, and fairly precise query without having to know that the column names were parking_valet and alcohol_bar. Further refinements? Let’s make sure it’s a nice restaurant, with average rating of 3.5+. To do this, we need to add a filter attribute with an inequality: (the Core API documentation on filters helps here):

  http://api.v3.factual.com/t/restaurants-us/read?
      q=dinner+valet+bar&
      filters={
         "locality":"New York",
         "rating":{
            "$gte":3.5
         }
      }&
      KEY=[your key]

 

In the end, your dinner date may, or may not, be successful, but we are doing all we can on the backend to help.

This release is just a start: it brings our previous restaurants table out of beta, adds structure to the attributes, and sets us up to add further countries and more attributes. We’re most excited about these releases because they provide the infrastructure for other good things to follow. We hope this type of functionality is useful, and look forward to your feedback.

Golda Velez
Factual Data Engineer