Skip to content

Factual's official Python driver for the Factual public API

License

Notifications You must be signed in to change notification settings

jebrown6/factual-python-driver

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

52 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

About

This is the Factual supported Python driver for Factual's public API.

This API supports queries to Factual's Read, Schema, Crosswalk, and Resolve APIs. Full documentation is available on the Factual website:

  • Read: Search the data
  • Schema: Get table metadata
  • Crosswalk: Get third-party IDs
  • Resolve: Enrich your data and match it against Factual's
  • Facets: Get counts of data by facet

Full documentation is available at http://developer.factual.com

If you need additional support, please visit http://support.factual.com

Warning

The driver also contains support for Submit and Flag requests which are not yet available through the Factual public API. These API features will be enabled in the near future.

Overview

Setup

The easiest way to get started with the driver is to install it from the Python Package Index.

pip install factual-api

Obtain an OAuth key and secret from Factual.

To use the driver in a python program, just create a Factual object using your OAuth key and secret.

from factual import Factual
factual = Factual(KEY, SECRET)

example.py is provided with the driver as a reference.

Dependencies

Requests

requests-oauth

Basic Design

The driver allows you to create an authenticated handle to Factual. With a Factual handle, you can send queries and get results back.

Queries are created using the Factual handle, which provides a fluent interface to constructing your queries. One thing to be aware of is the behavior of the query modifier functions. These return new query instances, so base queries can be set up and then modified in different ways to produce new queries.

# Create a base search query
q = factual.table("places").search("sushi")

# Use this query with a filter
filter_query = q.filters({"website":{"$blank":False}})

# Use the same base query with select parameters (will not have website filter applied)
select_name = q.select("name")

Tables

The Factual API is a generic API that sits over all tables available via the Factual v3 API. Some popular ones:

  • Table global for international places
  • Table restaurants-us for US restaurants only
  • Table places for US places only
  • Table products-cpg for consumer products

Unit Tests

Unit Tests are provided to ensure the driver and OAuth are functioning as expected.
Add your Oauth credentials to tests/test_settings.py From the command line, run: python -m tests.api_test

Simple Read Examples

# Return entities from the Places dataset where name equals "starbucks"
factual.table("places").filters({"name":"starbucks"}).data()
# Full text search for "sushi santa monica"
factual.table("places").search("sushi santa monica").data()
# Return entity names and non-blank websites from the Global dataset, for entities located in Thailand
factual.table("global").select("name,website").filters(
	{"country":"TH","website":{"$blank":False}}).data()
# Return highly rated U.S. restaurants in Los Angeles with WiFi
factual.table("restaurants-us").filters(
  {"$and":[{"locality":"los angeles"},{"rating":{"$gte":4}},{"wifi":"true"}]}).data()

Simple Crosswalk Example

# Get Crosswalk data using a Factual ID
FACTUAL_ID = "110ace9f-80a7-47d3-9170-e9317624ebd9"
query = factual.crosswalk().factual_id(FACTUAL_ID)
query.data()
# Get Crosswalk data using a third party namespace and namespace_id
SIMPLEGEO_ID = "SG_6XIEi3qehN44LH8m8i86v0"
query = factual.crosswalk().namespace('simplegeo',SIMPLEGEO_ID)
query.data()

Simple Resolve Example

# Returns resolved entities
query = factual.resolve({"name":"McDonalds","address":"10451 Santa Monica Blvd","region":"CA","postcode":"90025"})
query.data()
query.data()[1]["resolved"]  # true or false

Simple Facets Example

# Count the number of Starbucks per country
query = factual.facets("global").search("starbucks").select("country")
query.data()

More Read Examples

# 1. Specify the table Global
query = factual.table("global")
# 2. Filter results in country US
query = query.filters("country":"US")
# 3. Search for "sushi" or "sashimi"
query = query.search("sushi", "sashimi")
# 4. Filter by geolocation
query = query.geo({"$circle":{"$center":[34.06021, -118.41828], "$meters":5000}})
# 5. Sorting
query = query.sort("name:asc")       # ascending 
query = query.sort("name:desc")      # descending
# 6. Paging
query = query.offset("20")

Read API

All Top Level Query Parameters

Parameter Description Example
filters Restrict the data returned to conform to specific conditions. query = query.filters("name":{"$bw":"starbucks"})
include_count returns the total count of the number of rows in the dataset that conform to the query. query = query.include_count(True)
count = query.data().total_row_count()
geo Restrict data to be returned to be within a geographical range based. query.geo({"$circle":{"$center":[34.06021, -118.41828], "$meters":5000}})
limit Limit the results query = query.limit(12)
page Limit the results to a specific "page". query = query.page(2, :per:10)
search (across entity) Full text search across entity Find "sushi":
query = query.search("sushi")

Find "sushi" or "sashimi":
query = query.search("sushi", "sashimi")

Find "sushi" and "santa" and "monica":
query.search("sushi santa monica")

search (across field) Full text search on specific field query = query.filters({"name":{"$search":"cafe"}})
select Specifiy which fields to include in the query results. Note that the order of fields will not necessarily be preserved in the resulting response due to the nature Hashes. query = query.select("name,address,locality,region")
sort The field (or fields) to sort data on, as well as the direction of sort.

Sorts ascending by default, but supports both explicitly sorting ascending and descending, by using sort_asc or sort_desc. Supports $distance as a sort option if a geo-filter is specified.

Supports $relevance as a sort option if a full text search is specified either using the q parameter or using the $search operator in the filter parameter.

By default, any query with a full text search will be sorted by relevance.

Any query with a geo filter will be sorted by distance from the reference point. If both a geo filter and full text search are present, the default will be relevance followed by distance.

query = query.sort("name:asc")
query = query.sort("$distance:asc") query = query.sort("$distance:asc,name:desc")

Row Filters

The driver supports various row filter logic. For example:

# Returns records from the Places dataset with names beginning with "starbucks"
factual.table("places").filters("name":{"$bw":"starbucks"}).data()

Supported row filter logic

Predicate Description Example
$eq equal to query = query.filters("region":{"$eq":"CA"})
$neq not equal to query = query.filters("region":{"$neq":"CA"})
search full text search query = query.search("sushi")
$in equals any of query = query.filters("region":{"$in":["CA", "NM", "NY"]})
$nin does not equal any of query = query.filters("region":{"$nin":["CA", "NM", "NY"]})
$bw begins with query = query.filters("name":{"$bw":"starbucks"})
$nbw does not begin with query = query.filters("name":{"$nbw":"starbucks"})
$bwin begins with any of query = query.filters("name":{"$bwin":["starbucks", "coffee", "tea"]})
$nbwin does not begin with any of query = query.filters("name":{"$nbwin":["starbucks", "coffee", "tea"]})
$blank test to see if a value is (or is not) blank or null query = query.filters("tel":{"$blank":true})
query = query.filters("website":{"$blank":false})
$gt greater than query = query.filters("rating":{"$gt":7.5})
$gte greater than or equal query = query.filters("rating":{"$gte":7.5})
$lt less than query = query.filters("rating":{"$lt":7.5})
$lte less than or equal query = query.filters("rating":{"$lte":7.5})

AND

Filters can be logically AND'd together. For example:

# name begins with "coffee" AND tel is not blank
query = query.filters({ "$and":[{"name":{"$bw":"coffee"}}, {"tel":{"$blank":false}}] })

OR

Filters can be logically OR'd. For example:

# name begins with "coffee" OR tel is not blank
query = query.filters({ "$or":[{"name":{"$bw":"coffee"}}, {"tel":{"$blank":false}}] })

Combined ANDs and ORs

You can nest AND and OR logic to whatever level of complexity you need. For example:

# (name begins with "Starbucks") OR (name begins with "Coffee")
# OR
# (name full text search matches on "tea" AND tel is not blank)
query = query.filters({ "$or":[ {"$or":[ {"name":{"$bw":"starbucks"}},
                                               {"name":{"$bw":"coffee"}}]},
                                   {"$and":[ {"name":{"$search":"tea"}},
                                                {"tel":{"$blank":false}} ]} ]})

Full Documentation

Full documentation is available at http://developer.factual.com

About

Factual's official Python driver for the Factual public API

Resources

License

Stars

Watchers

Forks

Packages

No packages published