Can Neo4j Spatial Geoserver find the country, city given an ip address, if so, how to set up on nodes already created? - neo4j-spatial

I have some data in Neo4j with nodes having ip addresses as properties and I would like to get lat, lon (and city, country) data based on the ip address, similar to using geoip.dat. Can Neo4j Spatial give me this data? What are the steps to achieve this?

Neo4j spatial does not support finding location based on ip. You must use an API designed for getting location off of IP , like http://freegeoip.net/.. you can try calling this API directly with cypher
MATCH (m:Entity)
CALL apoc.load.json("http://freegeoip.net/json/?q=" + m.ip) YIELD value
//return response
RETURN value

Related

How to filter a range of IP addresses in a SQL query?

I am working in a web apps, I made some checking/limitation when user trying to login my application. Now i need to make a white list function to pass these checking make use of user ip address.
I'm trying to write a sql statement to get matched IP address in order to achieve white list. If the sql return data then pass the checking , if not just continue checking.
However, whitelist table in database need to be support 192.168.* or 192.* or (*. *.1.1) .So it will return data and pass if the user ip is 192.X.X.X
SELECT * FROM whitelist WHERE ip_address = $ip;
my sql statement like this.
I agree with #arno comment. If you have limited value to check then use regex instead of database call. It will save you time.
But if you want to call database then I remember that MySql support regex in query also
SELECT
*
FROM
whitelist
WHERE
ip_address REGEXP '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$';
Above regex is to check all valid IP address. But you can change it based on your requirement.
There is no natural case when you need to match something like *.*.1.1.
IP addresses are mostly matched according to subnets in their CIDR notation. Because this is how networks are organized.
Even simpler, you can convert IP addresses to a long datatype using INET_ATON() and make simple matches using > and <.
Please refer to these solutions:
Is there way to match IP with IP+CIDR straight from SELECT query?
https://dba.stackexchange.com/questions/171044/determining-if-an-ip-is-within-an-ipv4-cidr-block
You can use the LIKE statment:
SELECT * FROM whitelist WHERE ip_address LIKE '192.168.%';
The % character allows any character to replace it, therefore the above query will return IP adress in the range 192.168.0.0 - 192.168.255.255, provided you indeed only have IP adresses in this field.

Query to return rows that match a block of ip addresses?

I'm trying to block certain IP addresses and IP ranges from performing certain actions. Right now, I SELECT * FROM blocked WHERE ip=$_SERVER['REMOTE_ADDR'] and if ->num_rows returns > 0, I redirect the user.
This works with full IP addresses but if I put 199.90.*.* for example, into the database, how might I match that? Also, what would be the best way to store the IPs in the database?
The answer to your question is to use like:
SELECT *
FROM blocked
WHERE $_SERVER['REMOTE_ADDR'] like replace(ip, '*', '%')
The wildcard in like is '%' rather than '*', so this replaces the asterisk with the percent sign. I am guessing that you would actually store the string like '199.199.%.%', but the above is for clarity.
Although this technically solves your problem, it has other issues because MySQL may not use an index for these comparisons (see here). The impact depends on how large the blocked table is. If it has 100 rows, this may not be an issue. If it has 100,000 then it probably is.
An alternative to using wildcards for the blocked table is to have FromIP and ToIP as columns. Then something like "199.199.." would simply be stored as "199.199.000.000" and "199.199.999.999". The query would be:
where $_SERVER['REMOTE_ADDR'] between FromIP and ToIP
And you would have an index on blocked(FromIP, ToIP).
I would first check for full IP address, then mask out the last byte with *, and check for that, then the last 2 bytes, and so on. This way you go from specific to less specific, and if once you get a hit, the IP is blocked. It's probably not the most efficient way, but I guess you have to do it only once, at login-time.
I would store IP addresses for simplicity as strings.
Another solution could be to store IP address as byte-array, but that wouldn't make anything easier I guess, and would be much less maintainable with for example the command-line tool SQL tool.
Your best solution would be to use INET_ATON function.
Given the dotted-quad representation of an IPv4 network address as a string, returns an integer that represents the numeric value of the address in network byte order (big endian).
So, if you want to look for an IP in a certain range, you would use a Query like this:
SELECT * FROM blocked WHERE INET_ATON($_SERVER['REMOTE_ADDR']) between INET_ATON(this_ip) and INET_ATON(this_other_ip).
As I think, the best way to store IPv4 addresses in a MySQL Data base is using that function, to convert them to an int value and store it like that. And If you want to get the IP from it's int representation use INET_NTOA.
Storing IP's as int, the query ends like this:
SELECT * FROM blocked WHERE INET_ATON($_SERVER['REMOTE_ADDR']) between this_ip and this_other_ip.
And instead of using 199.90.*.* use (199.90.0.0).

Select items within range using MySQL spatial extensions?

I am completely new to MySQL spatial extensions, so please excuse my ignorance on the topic.
The scenario:
1) I collect a user's location via latitude and longitude. I store that location in a MySQL table.
2) I then display any other users within a range of that user. The range would be small - let's say 1000 ft.
Question:
What is the best practice for storing the location points? What is the best practice for querying and selecting the points nearest that user?
Use the POINT Spatial datatype to store the coordinates.
The structure is like this:
CREATE TABLE gps name varchar(0), `location` point NOT NULL;
Please note the type of column 'location'.
After that, you have to define a SPATIAL index for the 'location' column.
CREATE SPATIAL INDEX sp_index ON gps(`location`);
Inserting data (latitude and longitude)
INSERT INTO gps (name, location) VALUES ( 'India' , GeomFromText( ' POINT(31.5 42.2) ' ) )
The function GeomFromText takes a string and returns a Geometry Object. Here 31.5 and 42.2 are latitude and longitude respectively. Note that there is NO comma between them. They are delimited by a space.
Reading data
SELECT name, AsText(location) FROM gps;
The AsText function converts the internal representation of a geometry to a string format.
Note: You have to use MySQL 5.0 or above the spatial extension support. Also use 'MyIsam' db engine for faster queries.
Unfortunately there is no such function in MySQL as select points in radius. But you can easily use this cosine law formula: d = acos( sin(φ1)*sin(φ2) + cos(φ1)*cos(φ2)*cos(Δλ) )*R to get distance between 2 points. You can find details here: http://www.movable-type.co.uk/scripts/latlong-db.html
SQL query will look like this:
SELECT acos(sin(radians(Y(point1)))*sin(radians(Y(point2))) + cos(radians(Y(point1)))*cos(radians(Y(point2)))*cos(radians(X(point2))-radians(X(point1)))) * 6371 AS `distance`
FROM locations

MySql find country via geometry / spatial data

i want request my db with LAT/LON an get back a countrycode.
i have the world borders in a mysql database (converted shapefile from djangoproject.com) as geometry datafield.
When using
SELECT countyname FROM `world` WHERE Contains(ogc_geom, POINT(-18, 64))
i get back not only "iceland" (which is true) but also greenland, russia and usa.
I tried other points (point in mongolia founds also in china and russia), tried using intersects(), checked with multipolygons...
good ideas?
thanks, stefan
I am not sure you can do this only using MySQL. If you can interface the MySQL data with a scripting language, the n you can try the following.
Generate an image of the world map. Each pixel in the image will store the country id. You can lookup the country details from the MySQL db using this id.

How to store lat/long in MySQL database

I'm working on Google map API. after i choose the start and end point the map return the routed way as a path on the google map, and i have track the lat/lng from the routed path
as follows [ the coordinates below are the lat/long of a routed line]
13.692941, 100.750723,
13.70649,100.75405999999998,
13.71334,100.75428999999997,
13.72268,100.74638000000004,
13.72775,100.74631,
13.8153,100.73532999999998,
13.81332,100.73160000000007,
i want to store all these lat/long in MySQL database.
i found that there is Spatial extension in MySQL.
and there is a way to insert lat/long as linestring
insert into geom (g)
values (GeomFromText('linestring(2 3,7 5,10 10)'))
i wanna know how to add all those above lat long into linestring function?
or there is another suggestion?
You can store these lat/lon DATA like bellow -
$arr = array("13.692941, 100.750723",
"13.70649,100.75405999999998",
"13.71334,100.75428999999997",
"13.72268,100.74638000000004");
// serialize data before save to database, you should deserialized that when you will use this data after query.
$serializedArr = serialize($arr);
insert into geom (g) values ("{$serializedArr}");