Does anyone have a code sample using geojson shape in ElasticSearch 7.x shape query?
It works when I build the shape using ES builders, however I need to use geojson passed in (see below), which likely needs parsing of geojson into ES shape:
{"type":"Polygon","coordinates":[[[-82.30957031249999,26.657277674217585],[-81.7767333984375,25.84686509678058],[-80.90057373046875,24.986058021167594],[-80.25238037109375,25.16517336866393],[-79.97222900390625,26.08885491679362],[-79.771728515625,26.76277822801415],[-80.2606201171875,27.25707120788274],[-80.83740234375,27.332735136859146],[-81.529541015625,27.166695222253114],[-82.30957031249999,26.657277674217585]]]}
I've been struggling with this as well though I actually wanted to feed a JTS Geometry directly to a query. The solution I came up with was to use WrapperQueryBuilder to write the query in JSON:
import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
...
String queryName = "...";
String geoJson = "...";
QueryBuilder geoShapeQuery = QueryBuilders.wrapperQuery(
String.format(
"{ \"geo_shape\": { \"%s\": { \"shape\": %s, \"relation\": \"%s\" } } }",
queryName,
geoJson,
ShapeRelation.INTERSECTS.getRelationName()));
My query shapes are simple polygons, so I ended up converting it to an array of points and creating a polygon out of these:
if (null != shape) {
JSONObject jsonShape = new JSONObject(shape);
JSONArray coords = jsonShape.getJSONArray("coordinates");
CoordinatesBuilder cb = new CoordinatesBuilder();
for (Object coord: coords.getJSONArray(0)) {
JSONArray c = new JSONArray(coord.toString());
cb.coordinate((Double)c.get(0), (Double)c.get(1));
}
PolygonBuilder pb = new PolygonBuilder(cb);
gsqb = QueryBuilders.geoShapeQuery("FOOTPRINT", pb.buildGeometry());
}
Related
I am trying to move from Spring data elasticsearch 4.x to 5.x & spring-boot-starter-data-elasticsearch 3.0.0 in order to remove rhlc from my code.
One of my query is a geoShapeQuery
Here my old code :
GeoShapeQueryBuilder geoShape = QueryBuilders.geoShapeQuery(ConvertUtils.FULL_GEO,new Point(lon, lat));
geoShape.relation(ShapeRelation.CONTAINS);
QueryBuilder bool = new BoolQueryBuilder().filter(geoShape).should(rankFeature);
I am trying to use the new class of geoShapeQuery without success
JsonData shape = JsonData.of("{\"type\": \"point\",\"coordinates\": [ 13.0, 53.0 ]}");
Query geoShape = GeoShapeQuery.of(f->f.field(ConvertUtils.FULL_GEO)
.shape(s->s.relation(GeoShapeRelation.Contains).shape(shape)))._toQuery();
Query bool = BoolQuery.of(b->b
.filter(geoShape)
.should(rankFeature)
)._toQuery();
When I am debugging I am seeing that the geopshape object put the shape as a String instead of a JSON object.
Query: {"geo_shape":{"fullGeo":{"shape":"{"type": "point","coordinates": [ 13.0, 53.0 ]}","relation":"contains"}}}
I am expecting to have this (without the double quote):
Query: {"geo_shape":{"fullGeo":{"shape":{"type": "point","coordinates": [ 13.0, 53.0 ]},"relation":"contains"}}}
I don't know what I am doing wrong.
This is nothing from Spring Data Elasticsearch , it might be an issue in the Elasticsearch client. You might want to create an issue with Elasticsearch (https://github.com/elastic/elasticsearch-java/issues)
I am posting my solution if someone have the same issue...
My solution is to create a JSONObject via ObjectMapper (jackson) and then use JsonData
ObjectMapper om = new ObjectMapper();
var node = om.readTree("{\"type\": \"point\",\"coordinates\":["+ lon +","+ lat + "]}");
JsonData shape = JsonData.of(node);
Query geoShape = GeoShapeQuery.of(f->f.field(ConvertUtils.FULL_GEO)
.shape(s->s.relation(GeoShapeRelation.Contains).shape(shape)))._toQuery();
I am very new to Java programming, I would appreciate any kind of help.
So I want to display a set of lat-long coordinates (more than 50 coordinates) in Java-based canvas (e.g JFrame, Processing) from a WFS server. I have managed to parse lat-long value and print it to the console. Now I'm stuck in how to bring the lat-long coordinates to the screen coordinates (I'd like to draw it on 1000x500 size). I've tried to search for the reference but couldn't find the simplest one for a beginner like me. Here is the current part of my code :
String[] splitc = coord.split(",");
String lon = splitc[0];
String lat = splitc[1];
//parse string to float
float loncoord=Float.parseFloat(lon);
float latcoord=Float.parseFloat(lat);
Can I transfer the coordinates from the WFS to screen coordinates using world2screen.translate of Geotools library as in https://docs.geotools.org/latest/userguide/library/referencing/axis.html ?
In processing, there is a map() function (https://processing.org/reference/map_.html) to transfer from a range to another. I've tried it but it didn't work on my IDE.
One super noob question, I'm trying to store the WFS connection in a function so I can call it in another class, should I store it in static void or use "return"?
If someone can provide an example of a similar task, that would be very helpful. Thanks (Sara)
You can use this formula instead:
float x = ((WIDTH/360.0) * (180 + loncoord));
float y = ((HEIGHT/180.0) * (90 - latcoord));
It should work... Note that it returns a float and takes 5 arguments of the form:
map(input, inputMin, inputMax, outputMin, outputMax)
You only want to create the connection once, so you're left with two viable options: defining the connection as a static variable of a static class, or defining the connection as an instance variable of a class following the singleton pattern.
Assuming you chose the former approach, the method that returns the connection variable should therefore be static but not void:
public static connectionType getConnection() {
return connectionObject;
}
... where connectionType is the datatype of the connection.
The easiest way is to create a GeoTools WFSDataStore, this code builds up the getCapabilities string if the user has given just a URL to the service endpoint and handles authentication if needed. The datastore is stored in a field of the class:
public FetchWFS(String url, String user, String passwd) throws IOException, URISyntaxException {
if (!user.isEmpty()) {
auth = true;
}
baseURL = new URL(url);
List<NameValuePair> nvp = URLEncodedUtils.parse(baseURL.toURI(), "UTF-8");
NameValuePair service = new BasicNameValuePair("service", "wfs");
NameValuePair request = new BasicNameValuePair("request", "getCapabilities");
NameValuePair version = new BasicNameValuePair("version", "2.0.0");
HashMap<String, NameValuePair> parts = new HashMap<>();
parts.put(service.getName(), service);
parts.put(request.getName(), request);
parts.put(version.getName(), version);
for (NameValuePair part : nvp) {
if (part.getName().equalsIgnoreCase("SERVICE")) {
// We don't care what they think this should be
} else if (part.getName().equalsIgnoreCase("REQUEST")) {
// This must be getCapabuilities so we ignore them
} else if (part.getName().equalsIgnoreCase("VERSION")) {
System.out.println("Changing version to " + part.getValue());
parts.put(version.getName(), part);
} else {
parts.put(part.getName(), part);
}
}
URIBuilder builder = new URIBuilder();
builder.setScheme(baseURL.getProtocol());
builder.setHost(baseURL.getHost());
builder.setPort(baseURL.getPort());
builder.setPath(baseURL.getPath());
List<NameValuePair> p = new ArrayList<>();
p.addAll(parts.values());
builder.setParameters(p);
// builder.addParameter("viewparams", "q:\"mySolrQuery\"");
URI uri = builder.build();
System.out.println(uri);
baseURL = uri.toURL();
// fetch the DataStore
Map<String, Object> params = new HashMap<>();
params.put(WFSDataStoreFactory.URL.key, baseURL);
// params.put(WFSDataStoreFactory.WFS_STRATEGY.key, "mapserver");
if (auth) {
params.put(WFSDataStoreFactory.USERNAME.key, user);
params.put(WFSDataStoreFactory.PASSWORD.key, passwd);
}
// params.put(WFSDataStoreFactory.WFS_STRATEGY.key, "mapserver");
datastore = DataStoreFinder.getDataStore(params);
}
Once you have a DataStore (of any type) you can get a list of available
featureTypes and then add one (or more) of them to a map:
JMapFrame frame = new JMapFrame();
MapContent map = new MapContent();
String[] names = datastore.getNames();
featureSource = store.getFeatureSource(names[0]); //fetch first featureType
schema = featureSource.getSchema();
Style style = SLD.createSimpleStyle(schema);
this.layer = new FeatureLayer(featureSource, style);
map.addLayer(layer);
frame.enableToolBar(true);
frame.setMinimumSize(new Dimension(800, 400));
frame.setVisible(true);
The GeoTools Quickstart Tutorial will help you get started with simple mapping, and the Map Styling tutorial will allow you to generate a prettier map when you want more than a simple black and white default map.
I am trying to map .vcf to my DTO (Simple POJO) , here is what i have tried :
Code:
List<VCard> list = Ezvcard.parse(fr).all(); // fr is FileReader
SomeDto someDto = new SomeDto ();
List<SomeDto > someDtoList = new ArrayList<>();
for (Iterator<VCard> iterator = list.iterator(); iterator.hasNext();) {
VCard vCard = iterator.next();
c.setFirstName(vCard.getFormattedName().getValue());
c.setEmailAddress(vCard.getEmails().get(0).getValue());
c.setMobilePhone(vCard.getTelephoneNumbers().get(0).getText());
someDtoList .add(c);
}
return someDtoList ;
Is there a simplified way of handling this? Like in-built methods to take care if DTO has more properties, so we can avoid manual work?
I am using vCard JAR: https://github.com/mangstadt/ez-vcard
Maybe try this out https://github.com/mangstadt/ez-vcard it was originally a development by google and offers a lot of possibilities.
U may try to convert your vcards to json, to have more possibilities for further work.
String json = Ezvcard.writeJson(vcard).go();
I've been reading the H2O documentation for a while, and I haven't found a clear example of how to load model trained and saved using the Python API. I was following the next example.
import h2o
from h2o.estimators.naive_bayes import H2ONaiveBayesEstimator
model = H2ONaiveBayesEstimator()
h2o_df = h2o.import_file("http://s3.amazonaws.com/h2o-public-test-data/smalldata/airlines/allyears2k_headers.zip")
model.train(y = "IsDepDelayed", x = ["Year", "Origin"],
training_frame = h2o_df,
family = "binomial",
lambda_search = True,
max_active_predictors = 10)
h2o.save_model(model, path=models)
But if you check the official documentation it states that you have to download the model as a POJO from the flow UI. Is it the only way? or, may I achieve the same result via python? Just for information, I show the doc's example below. I need some guidance.
import java.io.*;
import hex.genmodel.easy.RowData;
import hex.genmodel.easy.EasyPredictModelWrapper;
import hex.genmodel.easy.prediction.*;
public class main {
private static String modelClassName = "gbm_pojo_test";
public static void main(String[] args) throws Exception {
hex.genmodel.GenModel rawModel;
rawModel = (hex.genmodel.GenModel) Class.forName(modelClassName).newInstance();
EasyPredictModelWrapper model = new EasyPredictModelWrapper(rawModel);
//
// By default, unknown categorical levels throw PredictUnknownCategoricalLevelException.
// Optionally configure the wrapper to treat unknown categorical levels as N/A instead:
//
// EasyPredictModelWrapper model = new EasyPredictModelWrapper(
// new EasyPredictModelWrapper.Config()
// .setModel(rawModel)
// .setConvertUnknownCategoricalLevelsToNa(true));
RowData row = new RowData();
row.put("Year", "1987");
row.put("Month", "10");
row.put("DayofMonth", "14");
row.put("DayOfWeek", "3");
row.put("CRSDepTime", "730");
row.put("UniqueCarrier", "PS");
row.put("Origin", "SAN");
row.put("Dest", "SFO");
BinomialModelPrediction p = model.predictBinomial(row);
System.out.println("Label (aka prediction) is flight departure delayed: " + p.label);
System.out.print("Class probabilities: ");
for (int i = 0; i < p.classProbabilities.length; i++) {
if (i > 0) {
System.out.print(",");
}
System.out.print(p.classProbabilities[i]);
}
System.out.println("");
}
}
h2o.save_model will save the binary model to the provided file system, however, looking at the Java application above it seems you want to use model into a Java based scoring application.
Because of that you should be using h2o.download_pojo API to save the model to local file system along with genmodel jar file. The API is documented as below:
download_pojo(model, path=u'', get_jar=True)
Download the POJO for this model to the directory specified by the path; if the path is "", then dump to screen.
:param model: the model whose scoring POJO should be retrieved.
:param path: an absolute path to the directory where POJO should be saved.
:param get_jar: retrieve the h2o-genmodel.jar also.
Once you have download POJO, you can use the above sample application to perform the scoring and make sure the POJO class name and the "modelClassName" are same along with model type.
I have JSON as a string and a JSONPath as a string. I'd like to query the JSON with the JSON path, getting the resulting JSON as a string.
I gather that Jayway's json-path is the standard. The online API, however, doesn't have have much relation to the actual library you get from Maven. GrepCode's version roughly matches up though.
It seems like I ought to be able to do:
String originalJson; //these are initialized to actual data
String jsonPath;
String queriedJson = JsonPath.<String>read(originalJson, jsonPath);
The problem is that read returns whatever it feels most appropriate based on what the JSONPath actually finds (e.g. a List<Object>, String, double, etc.), thus my code throws an exception for certain queries. It seems pretty reasonable to assume that there'd be some way to query JSON and get JSON back; any suggestions?
Java JsonPath API found at jayway JsonPath might have changed a little since all the above answers/comments. Documentation too. Just follow the above link and read that README.md, it contains some very clear usage documentation IMO.
Basically, as of current latest version 2.2.0 of the library, there are a few different ways of achieving what's been requested here, such as:
Pattern:
--------
String json = "{...your JSON here...}";
String jsonPathExpression = "$...your jsonPath expression here...";
J requestedClass = JsonPath.parse(json).read(jsonPathExpression, YouRequestedClass.class);
Example:
--------
// For better readability: {"store": { "books": [ {"author": "Stephen King", "title": "IT"}, {"author": "Agatha Christie", "title": "The ABC Murders"} ] } }
String json = "{\"store\": { \"books\": [ {\"author\": \"Stephen King\", \"title\": \"IT\"}, {\"author\": \"Agatha Christie\", \"title\": \"The ABC Murders\"} ] } }";
String jsonPathExpression = "$.store.books[?(#.title=='IT')]";
JsonNode jsonNode = JsonPath.parse(json).read(jsonPathExpression, JsonNode.class);
And for reference, calling 'JsonPath.parse(..)' will return an object of class 'JsonContent' implementing some interfaces such as 'ReadContext', which contains several different 'read(..)' operations, such as the one demonstrated above:
/**
* Reads the given path from this context
*
* #param path path to apply
* #param type expected return type (will try to map)
* #param <T>
* #return result
*/
<T> T read(JsonPath path, Class<T> type);
Hope this help anyone.
There definitely exists a way to query Json and get Json back using JsonPath.
See example below:
String jsonString = "{\"delivery_codes\": [{\"postal_code\": {\"district\": \"Ghaziabad\", \"pin\": 201001, \"pre_paid\": \"Y\", \"cash\": \"Y\", \"pickup\": \"Y\", \"repl\": \"N\", \"cod\": \"Y\", \"is_oda\": \"N\", \"sort_code\": \"GB\", \"state_code\": \"UP\"}}]}";
String jsonExp = "$.delivery_codes";
JsonNode pincodes = JsonPath.read(jsonExp, jsonString, JsonNode.class);
System.out.println("pincodesJson : "+pincodes);
The output of the above will be inner Json.
[{"postal_code":{"district":"Ghaziabad","pin":201001,"pre_paid":"Y","cash":"Y","pickup":"Y","repl":"N","cod":"Y","is_oda":"N","sort_code":"GB","state_code":"UP"}}]
Now each individual name/value pairs can be parsed by iterating the List (JsonNode) we got above.
for(int i = 0; i< pincodes.size();i++){
JsonNode node = pincodes.get(i);
String pin = JsonPath.read("$.postal_code.pin", node, String.class);
String district = JsonPath.read("$.postal_code.district", node, String.class);
System.out.println("pin :: " + pin + " district :: " + district );
}
The output will be:
pin :: 201001 district :: Ghaziabad
Depending upon the Json you are trying to parse, you can decide whether to fetch a List or just a single String/Long value.
Hope it helps in solving your problem.
For those of you wondering why some of these years-old answers aren't working, you can learn a lot from the test cases.
As of September 2018, here's how you can get Jackson JsonNode results:
Configuration jacksonConfig = Configuration.builder()
.mappingProvider( new JacksonMappingProvider() )
.jsonProvider( new JacksonJsonProvider() )
.build();
JsonNode node = JsonPath.using( jacksonConfig ).parse(jsonString);
//If you have a json object already no need to initiate the jsonObject
JSONObject jsonObject = new JSONObject();
String jsonString = jsonObject.toString();
String path = "$.rootObject.childObject"
//Only returning the child object
JSONObject j = JsonPath.read(jsonString, path);
//Returning the array of string type from the child object. E.g
//{"root": "child":[x, y, z]}
List<String> values = sonPath.read(jsonString, path);
Check out the jpath API. It's xpath equivalent for JSON Data. You can read data by providing the jpath which will traverse the JSON data and return the requested value.
This Java class is the implementation as well as it has example codes on how to call the APIs.
https://github.com/satyapaul/jpath/blob/master/JSONDataReader.java
Readme -
https://github.com/satyapaul/jpath/blob/master/README.md