Maps! Range index Scoring! And other such cool visual stuff for MarkLogic web apps! Read on…
Maps! Yey! So MarkLogic’s OOTB Application Builder (aka AppBuilder) has had google maps with polygon, circle selections and heatmap overlays for a while.
This is great, but I wondered if I could give it the MLJS treatment and see what else could be achieved…
Back in the day (when I were a lad knee high t’ grass’opper) I wrote a helluva lot of code for a walking route planning application. Turns out theres no money in it, but it did mean I got to combine two of my geek loves – maps and computers!
What this means in practical terms is that you can plug any number of mapping tile layers, marker (pin) overlays, or vector overlays on top of it. So I can have a google map, or click a button and suddenly I have the same zoom level and view, but with an Open Street Map (OSM)!
Very flexible, very easy to get going with, and many, many samples available.
OpenLayers and MarkLogic
I decided to use this with MarkLogic for a couple of reasons. Firstly, it’s sheer awesomeness in a js file. (This is the part where my wife gets jealous of my computer… again)
Secondly though, the main gap between AppBuilder and MLJS at the moment is mapping. Given the number of geospatial use cases (and the fact I have some work coming up that needs a solid map of the UK in better detail than google) MarkLogic fronts, I thought I’d best plug the hole.
What I’ve come up with is pretty special. It can:-
- Be configured with any mapping layer (including multiples) OpenLayers supports (Including OSM, Google, Bing, ArcGIS, WMS and more…)
- Supports *multiple* ‘series’ of search results, represented as different coloured marker sets, each driven from a different query
- Introspect result documents to extract longitude, latitude, point title, and summary – creating a marker and popup for each
- Caches map tiles using a ‘try cache first’ algorithm – useful if doing a demonstration of mapping where there is no internet connection – just do the demo in the office first before hand and keep the web page open!
- Converts co-ordinates automatically between MarkLogic/stored WGS84/EPSG:4326 degrees lat/lon and the web mapping layers’ EPSG:900913 metres lat/lon for map centre and search results
- In Progress: Support contributing a structured query term through circle (radius), polygon and rectangle area selection (including free hand polygon tracing by holding down ‘shift’ and click-dragging!)
Don’t believe me though, take a look at this image!:-
Search selection widget
What you’ll probably also notice is that there is a relevancy method drop down widget, and that the results widget is sorted by distance from the centre of my map!
The relevancy widget is actually a ‘searchselection’ widget, linked to two saved queries – ‘Nearest First’ and ‘Highest Rated First’. This is pretty useful to execute pre-prepared and complex searches.
What’s even better is that I’ve added an extra function to the query builder (create one with db.createQuery() ) called dynamic(). This function allows you to provide a query term, but also allows you to overwrite it dynamically at query time through a callback!
No more creating the full query from scratch each time in a monolithic controller – just alter the clause you need with a list of variables. (Currently dynamic() only supports geoElementPairPoint and geoElementPairCircle queries).
MarkLogic 7 Range Index Scaling
The ‘nearest to centre’ functionality was possible by using MarkLogic 7’s range index scoring support. This allows you to alter the relevance of a particular document (in my case a tourist attraction description) by the value of it’s range indexes, and for geospatial queries, distance from the calculated centre of the circle/polygon the match is from.
In version 6 you could only do ‘show me all attractions in 20 miles’ now in version 7 you can ask ‘show me all attractions in 20 miles, with the most relevant matches being the nearest’. You can even provide a scale-factor to determine how much the value affects relevancy.
The demo above does this range scoring for geospatial (distance) and integer (star rating) range indexes configured over the matching document set.
Other recent additions
I’ve made a bunch of other changes, mainly to the options builder and query builder objects in the Core API (mljs.js) to allow for more controlled and a wider range of queries to be performed. I’ve found a bunch of bugs in range index options handling which are now fixed, and added support for pathConstraints and fieldConstraints in search options finally.
Support for static and dynamic (time) bucketing in search options has also been added to MLJS Core and the mldbwebtest Roxy test application. The Ontology builder functionality within the tripleconfig object has been rounded out, and is now used by default. This makes it much easier and less buggy to add new RDF types and predicates between types to a configured Ontology.
Finally, I’ve added search options and document get support for transformations. This allows a whole search result set on search, and a document on fetch, to be transformed using a specified XQuery module.
When can you get it?
Testing should complete by the end of November 2013. I’ll push the changes to MASTER on GitHub then (and npm and the download files). For now, they are only available on the dev branch until I’ve fully tested them.
Those of you keeping a close eye on my mldbwebtest project may well have spotted the ‘Workplace’ page. This looks suspiciously like the Search Page except for the inclusion of a couple of HighCharts widgets.
I’ve been playing around with the concept of creating a mechanism to store the configuration of a page ‘layout’, and any contained widgets (and indeed sub-layouts). At the moment this means you have to hand crank some horrendous JSON to describe a page.
Sounds a bit pointless, right? Wrong! Imagine if rather than coding this, you instead clicked on an ‘edit’ button on the page – much like you do in Portal environments – and were given a drag/drop way to layout widgets, and create multiple pages?
I’ve also re-themed the blog here! Please subscribe to the blog or my twitter account for future updates. Please send me information on any new features you’d like to see!