How to get ids from Freebase given part of a name? - api

When I go to Freebase.com and search for bush (for example), I get suggestions like George Bush, Kate Bush, George H.W. Bush etc.
How can I get that list as IDs from the query api?
I am trying to get the a list, like this, of ids for a particular name:
[{
"id": null,
"name": "bush",
}]

You can use the search API
https://www.googleapis.com/freebase/v1/search?query=bush
or if you want to use MQL, use can use the contains operator (~=)
https://www.googleapis.com/freebase/v1/mqlread?query=[{%22name~=%22:%20%22bush%22,%20%22id%22:null}]
The contains operator does whole word matching by default. If you want partial word matches, you can add additional wild cards, but you risk running into timeouts, particularly for leading wildcards.
https://www.googleapis.com/freebase/v1/mqlread?query=[{%22name~=%22:%20%22*bush*%22,%20%22id%22:null}]

Related

REST API and GET with structured data

I'm designing a REST API where given an address, I will return the timezone corresponding to the address. I started along this path,
GET /api/TimeZone?address=
Now this address is a free form address field that I need to parse on the server.
To avoid errors, I'd really like to have the user send in a record like {"city": "", "state": "", "country": "" }
But I can only do this using a POST or a PUT endpoint => which semantically implies that the data is changing on the server but its actually NOT.
What would be a good way to address this?
You can have multiple fields in your query:
TimeZone?city=London&country=uk
Or if you could use hierarchical URLs such as:
TimeZone/UK
TimeZone/UK/London
I would expect the first of these to supply a bunch of cities, such as those found in most clocks, for UK, London would be the only suggestion as the whole of the UK is "London Time", but for America, there would be many suggestions.

Find relation between two entities in Freebase

I am new in Freebase and I have a simple question . I would like to use Freebase KB to find relation between two entities. For example if I have name entities "Washington" and "United States" , I would like to send a query to Freebase and get :
Location/Location/Capital or Null in the case of No relation.
Thank you very much.
If you only want to go one ply out (ie nearest neighbors), this is pretty simple to do using the reflection API if you're using the online version of Freebase. If you're using the bulk downloads, you'll need to work with whatever query engine you're using (probably SPARQL unless you converted the RDF to something else).
If you want to find the shortest path(es) regardless of who far apart they are, it becomes a graph search algorithm.
EDIT: If you only want to find capitols, you can fill in your IDs in this query:
[{
"type": "/location/administrative_division_capital_relationship",
"capital": [{
"id": null
}],
"administrative_division": [{
"id": null
}],
"limit": 1
}]
Note that for Washington, D.C., this will return null because the data isn't in Freebase.
If you need to handle arbitrary properties, you'll need to use reflection. See https://developers.google.com/freebase/mql/ch03#reflection

Creating Mandatory User Filters with multiple element IDs

Mandatory User Filters
I am working on a tool to allow customers to apply Mandatory User Filters. When attributes are loaded like "Year" or "Age", each can have hundreds of elements with the subsequent ids. In the POST request to create a filter (documented here: https://developer.gooddata.com/article/lets-get-started-with-mandatory-user-filters), looks like this:
{
"userFilter": {
"content": {
"expression": "[/gdc/md/{project-id}/obj/{object-id}]=[/gdc/md/{project-id}/obj/{object-id}/elements?id={element-id}]"
},
"meta": {
"category": "userFilter",
"title": "My User Filter Name"
}
}
}
In the "expression" property, it notes how one ID could be set. What I want is to have multiple ids associated with the object-id set with the post. For example, if I user wanted to add a filter to all of the elements in "Year" (there are 150) in the demo project, it seems odd to make 150 post requests.
Is there a better way?
UPDATE
Tomas thank you for your help.
I am not having trouble assigning multiple userfilters to a user. I can easily apply a singular filter to a user with the method outlined in the documentation. However, this overwrites the userfilter field. What is the syntax for this?
Here is my demo POST data:
{ "userFilters":
{ "items": [
{ "user": "/gdc/account/profile/decd0b2e3077cf9c47f8cfbc32f6460e",
"userFilters":["/gdc/md/a1nc4jfa14wey1bnfs1vh9dljaf8ejuq/obj/808728","/gdc/md/a1nc4jfa14wey1bnfs1vh9dljaf8ejuq/obj/808729","/gdc/md/a1nc4jfa14wey1bnfs1vh9dljaf8ejuq/obj/808728"]
}
]
}
}
This receives a BAD REQUEST.
I'm not sure what you mean by "have multiple ids associated with the object-id" exactly, but I'll try to tell you all I know about it. :-)
If you indeed made multiple POST requests, created multiple userFilters and set them all for one user, the user wouldn't see anything at all. That's because the system combines separate userFilters using logical AND, and a Year cannot be 2013 and 2014 at the same time. So for the rest of my answer, I'll assume that you want OR instead.
There are several ways to do this. As you may have guessed by now, you can use AND/OR explicitly, using an expression like this:
[/…/obj/{object-id}]=[/…/obj/{object-id}/elements?id={element-id}] OR [/…/obj/{object-id}]=[/…/obj/{object-id}/elements?id={element-id}]
This can often be further simplified to:
[/…/obj/{object-id}] IN ( [/…/obj/{object-id}/elements?id={element-id}], [/…/obj/{object-id}/elements?id={element-id}], … )
If the attribute is a date (year, month, …) attribute, you could, in theory, also specify ranges using BETWEEN instead of listing all elements:
[/…/obj/{object-id}] BETWEEN [/…/obj/{object-id}/elements?id={element-id}] AND [/…/obj/{object-id}/elements?id={element-id}]
It seems, though, that this only works in metrics MAQL and is not allowed in the implementation of user filters. I have no idea why.
Also, for your own attribute like Age, you can't do that since user-defined numeric attributes aren't supported. You could, in theory, add a fact that holds the numeric value, and construct a BETWEEN filter based on that fact. It seems that this is not allowed in the implementation of user filters either. :-(
Hope this helps.

The RESTful way to include or not include children of a resource?

Say I have a team object, that has a name property, a city property and a players property, where the players property is a an array of possibly many players. This is represented in an SQL database with a teams table and a players table, where each player has a name and a team_id.
Building a RESTful api based on this simple data-structure, I'm in doubt if there is a clear rule regarding, if the return object should/could include a list of players, when hitting /teams/:id ?
I have a view, that needs to show a team, and its players with their names, so:
1: Should /teams/:id join the two tables behind the scene and return the full team object, with a players property, that is an array of names and id's?
2: Should /teams/:id join the two tables behind the scene and return the team object, with a players property, that is an array of just id's that will then have to be queried one-by-one to /players/:id ?
3: Should two calls be made, one to /teams/:id and one to /teams/:id/players ?
4: Should a query string be used like this /teams/:id?fields=name,city,players ?
If either 2 or 3 is the way to go, how would one approach the situation, where a team could also have multiple cities, resulting in another cities table in the DB to keep it normalized? Should a new endpoint then be created at /teams/:id/cities.
When creating RESTful API's, is it the normalized datastructure in the DB that dictates the endpoints in the API?
Usually with a RESTful API, it is best that the use-cases dictate the endpoints of the API, not necessarily the data structure.
If you sometimes need just the teams, sometimes need just the players of a team, and sometimes need both together, I would have 3 distinct calls, probably something like /teams/:id, /players/:teamid and player-teams/:teamid (or something similar).
The reason you want to do it this way is because it minimizes the number of HTTP requests that need to be made for any given page. Of all of the typical performance issues, an inflated number of HTTP requests is usually one of the most common performance hits, and usually one of the easiest to avoid.
That being said, you also don't want to go so crazy that you create an over-inflated API. Think through the typical use cases and make calls for those. Don't just implement every possible combination you can think of just for the sake of it. Remember You Aren't Gonna Need It.
I'd suggest something like:
GET /teams
{
"id" : 12,
"name" : "MyTeam"
"players" :
{
"self" : "http://my.server/players?teamName=MyTeam"
},
"city" :
{
"self" : "http://my.server/cities/MyCity"
}
}
GET /cities
GET /cities/{cityId}
GET /players
GET /players/{playerId}
You can then use URIs to call out to get whatever other related resources you need. If you want the flexibility to embed values, you can use ?expand, such as:
GET /teams?expand=players
{
"id" : 12,
"name" : "MyTeam"
"players" :
{
"self" : "http://my.server/players?teamName=MyTeam",
[
{
"name" : "Mary",
"number" : "12"
},
{
"name" : "Sally",
"number" : "15"
}
]
},
"city" :
{
"self" : "http://my.server/cities/MyCity"
}
}

How do ldap search for email address in contacts' 2nd/3rd alternate email addresses?

I have an LDAP server with my email contacts so that I can lookup contacts by name/email, etc. However, it only seems to search and find the first email address for any contact.
For example, if I have a person:
LastName: Doe
FirstName: John
Email: jdoe#work.com
Email2: johndoe#home.com
Email3: johndoe#fun.com
It only searches through or returns the first email. For example, if I search for "John", it will return only the "jdoe#work.com" even though the other two email addresses have "john" in them. The search filters I've tried are:
//This one will both look through and match the first email but ignores the 2nd/3rd
(|(displayName=*%v*)(mail=*%v*)(uid=*%v*)(givenname=*%v*)(sn=*%v*)(cn=*%v*))
//This one throws an error saying "mail2" and "mail3" are invalid filters.
(|(displayName=*%v*)(mail=*%v*)(mail2=*%v*)(mail3=*%v*)(uid=*%v*)(givenname=*%v*)(sn=*%v*)(cn=*%v*))
What should I be using?
Also, does anyone have a link to some page that lists all the possible filters I can put in an ldap person search?
Exchange does not store additional mailaddresses in fields like mail2 or mail3. All addresses are stored in the multi-valued field "proxyAddresses". This field contains one line for each address in the form of
address-type:address
Example:
smtp:test#contoso.local
SMTP:user#contoso.local
The second entry in the example would be main address for that account, because the SMTP prefix is all uppercase.
So you would search for (proxyAddress=%v) or something like that. I don't know the LDAP search syntax out of my head.
Edit: Another option is to use the ResolveNames operation of the EWS webservices (see http://www.infinitec.de/post/2009/04/13/Resolving-the-primary-email-address-with-Exchange-WebServices-ResolveNames-operation.aspx and http://msdn.microsoft.com/en-us/library/aa563518(v=exchg.140).aspx).
The filter:
(|(displayName=*%v*)(mail=*%v*)(uid=*%v*)(givenname=*%v*)(sn=*%v*)(cn=*%v*))
will not match the entry:
LastName: Doe
FirstName: John
Email: jdoe#work.com
Email2: johndoe#home.com
Email3: johndoe#fun.com
because none of the filter assertions match any of the attribute names in the given entry.
(|(Email=jd*)(Email2=john*)(Email3=john*)(lastName=Do*))
would match. Have you considered using the standard names for the example entry you give?
Active Directory was released with some schema choices that are questionable. Now it is hard to fix them.
One of those is that mail, was flagged as single valued. This should have been a multivalued attribute. Thus the use of proxyAddresses, where it tries to overload a string syntax attribute with more information by using smtp: or x500: or SIP: to indicate a protocol for the address. Then upper case (SMTP) means primary and lower case (smtp) means secondary.
This also occured for telephoneNumber being single valued, and extra values now overflow into the attribute otherPhone.
Same for:
facsimileTelephoneNumber and otherFacsimileTelephoneNumber
labelledUri and url
homePhone and otherHomePhone
pager and otherPager
mobile and otherMobile