I am looking for an public Rest API which I can consume and get random city name at every time.
No inputs (like country). City can be any size, it can be a village, town, city..
I've developed and host an online city database called GeoDB Cities which should fit the bill. Here's how I would implement a Random-City-Name feature:
Do an initial query to get the total count of all available cities. The results are chunked by pages, but each result also contains metadata about the total count of cities. You need to extract metadata.totalCount
from the JSON. (You can safely cache this value.)
GET http://geodb-free-service.wirefreethought.com/v1/geo/cities?hateoasMode=off
Get a random number from 0 to (totalCount - 1)
in the previous step (results are zero-based). Go here for an excellent example of how to do so in Java. The code in other languages should look similar. This will represent your offset result into the data.
Do another GET query to get a single offset result, where OFFSET is zero-based. Extract data.name
from the JSON.
GET http://geodb-free-service.wirefreethought.com/v1/geo/cities?limit=1&offset=OFFSET&hateoasMode=off
The free instance is limited to cities with populations of at least 40000, but that might be fine for your purposes.
You can use Wikidata with a SPARQL query, which may be useful if you also want some facts about the city
SELECT DISTINCT ?city ?label WHERE {
?city rdfs:label ?label.
?city wdt:P31 wd:Q515.
FILTER((LANG(?label)) = "en")
}
ORDER BY UUID()
LIMIT 10
Note1 : UUID() is to give random results. RAND() doesn't work with Wikidata (source).
Note2: I put in LIMIT 10
to show more results, but in your case set it to 1
Note3: Be careful of browser caching
You can access the SPARQL endpoint with your code (documentation) with this URL (currently XML output)
https://query.wikidata.org/sparql?query=SELECT%20DISTINCT%20%3Fcity%20%3Fcountry%20%3Flabel%20WHERE%20%7B%0A%20%20%3Fcity%20rdfs%3Alabel%20%3Flabel.%0A%20%20%3Fcity%20wdt%3AP31%20wd%3AQ515.%0A%20%20FILTER((LANG(%3Flabel))%20%3D%20%22en%22)%0A%7D%0AORDER%20BY%20UUID()%0ALIMIT%2010
SELECT ?cityLabel { { SELECT * { ?city wdt:P31 wd:Q515 } ORDER BY uuid() LIMIT 1 } SERVICE wikibase:label { bd:serviceParam wikibase:language "en" } }
should by slightly faster here, but there is a chance to get something like Q21095147 as a result.
Commented
Nov 22, 2018 at 18:09