Queries
The expanded query API is capable of processing both traditional data queries and geo queries using a simple, yet powerful, SQL-like language. The ml.query function returns an instance of the ml.data.Query class providing the methods necessary to query large data sets quickly using a fluent interface.
<html> <head> <script type="text/javascript" src="/JS"></script> <script type="text/javascript"> ml.onload(function () { var q = ml.query().from('maplarge/Donors').where('PartyCode', 'Contains', 'r').groupby('State'); q.select('State').select('Amount.sum').orderby('Amount'); q.run(function (data, query) { var dataDiv = document.getElementById('dataDiv'); dataDiv.innerHTML = ml.util.toJSON(data); }); }); </script> </head> <body> <div id="dataDiv"></div> </body> </html>
The Return Object from the server is a JSON object which contains two Objects, data and totals. The data object contains all non-aggregate data from the query. Grouped aggregate data is contained in the totals data object following the naming convention columnName.aggregateName.
Filtering by column data includes
Contains, Does Not Contain, Greater Than, Equal To, etc.
Filtering by geospatial shapes
(geo queries) includes Polyline, Polygon, Freehand Polygon, Circle, Point, etc
Name | Description |
---|---|
Operators | Although syntactically different than SQL, the language is similar using operators named select, from, where, groupby, orderby, take and start. Aggregate functions min, max, avg, sum and count are also supported. To use an aggregate function, append the function to the field name using a dot (period). For example, the column namedStarRating would become StarRating.avg. All columns can be requested using an asterisk within a single select method, for example select(‘*’). Row counts can be calculated using select(‘*.count’). This naming convention provides a familiar feel to the language and combined with the fluent interface, insures the resulting queries are easy to read. |
Data Output | Data is returned within a JSON object via an AJAX callback, or as a downloaded CSV file. By default, the return value is an object literal containing two properties, data and totals. The data properties value is an object literal with one property for each column whose value is an array of values. The transposeQueryData method accepts the default return object data value and returns an array containing an array for each row of data, including the column names (see example below). |
The first example is documented below and steps through the process of defining a query, from beginning through execution. All examples will use a table containing hotel data. The hotels are located around the world and each is represented visually by a point on a map.
The first example is separated by operator/keyword to show the progression of building the query and for ease of explanation; however, the same example could have been done in one single line or broken down in any way necessary to meet requirements.
Constructor: Create an instance of the ml.data.Query class using the ml.query helper function:
var q = ml.query();
From: Define the table to query:
q.from(‘hms/hotels’);
Select: the fields to include in the return dataset:
q.select(‘HotelName’).select(‘CityName’).select(‘StarRating’);
Take: the number of records to retrieve (if no limit is specified a default limit of 100 is applied):
q.take(3);
Run: run this query and write the contents to the browser console:q.run(function(results) {
console.log(results);
// Only output the data is there is data:
if (results.data) {
makeTable(ml.$('#results'), results.data);
} else {
console.log('Query failed.');
}
});
Additional Examples
<html> <head> <script type="text/javascript" src="/JS"></script> <script type="text/javascript"> ml.onload(function() { // create our query object var q = ml.query(); // select data from the 'hms/hotels' table q.select('HotelName').select('CityName').select('StarRating'); q.from('hms/hotels'); // narrow down our example using Where Clause q.where('CityName', 'Contains', 'Ber'); // execute our query, capture results with the callback function q.run(function(results) { // let's hand off the results for display.... makeTable(ml.$('#results'), results.data ); }); /****************************************** Helper Function to Layout the Data ******************************************/ function makeTable(container, data) { // let's transpose our data in rows var rows = ml.data.query.Query.transposeQueryData(data); // get our column headings var head = []; ml.each(rows[0], function(k,v) { head.push(k); }); rows.unshift(head); data=rows; var table = ml.$("<table/>").addClass('CSSTableGenerator'); ml.$.each(data, function(rowIndex, r) { var row = ml.$("<tr/>"); ml.$.each(r, function(colIndex, c) { var content = "<p>"+c+"</p>"; row.append(ml.$("<t"+(rowIndex == 0 ? "h" : "d")+"/>").html(content)); }); table.append(row); }); return container.append(table); } }); </script> </head> <body> <div id="results" style="width:100%;height:100%;"></div> </body> </html>
<html> <head> <script type="text/javascript" src="/JS"></script> <script type="text/javascript"> ml.onload(function() { // create our query object var q = ml.query(); // select data from the 'hms/hotels' table q.select('HotelName').select('CityName').select('StarRating'); q.from('hms/hotels'); // narrow down our example using Where Clause q.where('CityName', 'Contains', 'Ber'); // we only need 10 records q.take(10); // execute our query, capture results with the callback function q.run(function(results) { // let's hand off the results for display.... makeTable(ml.$('#results'), results.data ); }); /****************************************** Helper Function to Layout the Data ******************************************/ function makeTable(container, data) { // let's transpose our data in rows var rows = ml.data.query.Query.transposeQueryData(data); // get our column headings var head = []; ml.each(rows[0], function(k,v) { head.push(k); }); rows.unshift(head); data=rows; var table = ml.$("<table/>").addClass('CSSTableGenerator'); ml.$.each(data, function(rowIndex, r) { var row = ml.$("<tr/>"); ml.$.each(r, function(colIndex, c) { var content = "<p>"+c+"</p>"; row.append(ml.$("<t"+(rowIndex == 0 ? "h" : "d")+"/>").html(content)); }); table.append(row); }); return container.append(table); } }); </script> </head> <body> <div id="results" style="width:100%;height:100%;"></div> </body> </html>
<html> <head> <script type="text/javascript" src="/JS"></script> <script type="text/javascript"> ml.onload(function() { // create our query object var q = ml.query(); // select data from the 'hms/hotels' table q.select('HotelName').select('CityName').select('StarRating'); q.from('hms/hotels'); // narrow down our example using Where Clause q.where('CityName', 'Contains', 'Ber'); // we only need 10 records q.take(10); // let's control the order, ASCENDING by default q.orderby('CityName'); // execute our query, capture results with the callback function q.run(function(results) { // let's hand off the results for display.... makeTable(ml.$('#results'), results.data ); }); /****************************************** Helper Function to Layout the Data ******************************************/ function makeTable(container, data) { // let's transpose our data in rows var rows = ml.data.query.Query.transposeQueryData(data); // get our column headings var head = []; ml.each(rows[0], function(k,v) { head.push(k); }); rows.unshift(head); data=rows; var table = ml.$("<table/>").addClass('CSSTableGenerator'); ml.$.each(data, function(rowIndex, r) { var row = ml.$("<tr/>"); ml.$.each(r, function(colIndex, c) { var content = "<p>"+c+"</p>"; row.append(ml.$("<t"+(rowIndex == 0 ? "h" : "d")+"/>").html(content)); }); table.append(row); }); return container.append(table); } }); </script> </head> <body> <div id="results" style="width:100%;height:100%;"></div> </body> </html>
<html> <head> <script type="text/javascript" src="/JS"></script> <script type="text/javascript"> ml.onload(function() { // create our query object var q = ml.query(); // select data from the 'hms/hotels' table q.select('HotelName').select('CityName').select('StarRating'); q.from('hms/hotels'); // narrow down our example using Where Clause q.where('CityName', 'Contains', 'Ber'); // we only need 10 records q.take(10); // let's control the order, DESCENDING by appending '.desc' to the column name q.orderby('CityName.desc'); // execute our query, capture results with the callback function q.run(function(results) { // let's hand off the results for display.... makeTable(ml.$('#results'), results.data ); }); /****************************************** Helper Function to Layout the Data ******************************************/ function makeTable(container, data) { // let's transpose our data in rows var rows = ml.data.query.Query.transposeQueryData(data); // get our column headings var head = []; ml.each(rows[0], function(k,v) { head.push(k); }); rows.unshift(head); data=rows; var table = ml.$("<table/>").addClass('CSSTableGenerator'); ml.$.each(data, function(rowIndex, r) { var row = ml.$("<tr/>"); ml.$.each(r, function(colIndex, c) { var content = "<p>"+c+"</p>"; row.append(ml.$("<t"+(rowIndex == 0 ? "h" : "d")+"/>").html(content)); }); table.append(row); }); return container.append(table); } }); </script> </head> <body> <div id="results" style="width:100%;height:100%;"></div> </body> </html>
<html> <head> <script type="text/javascript" src="/JS"></script> <script type="text/javascript"> ml.onload(function() { // create our query object var q = ml.query(); // select data from the 'hms/hotels' table q.select('CityName'); q.from('hms/hotels'); // narrow down our example using Where Clause q.where('CityName', 'Contains', 'Ber'); // we only need 10 records q.take(10); // let's group our data by CityName q.groupby('CityName'); // select a field with an aggregate applied q.select('StarRating.sum'); // let's control the order using our aggregated field q.orderby('StarRating.sum.desc'); // execute our query, capture results with the callback function q.run(function(results) { // let's hand off the results for display.... makeTable(ml.$('#results'), results.data ); }); /****************************************** Helper Function to Layout the Data ******************************************/ function makeTable(container, data) { // let's transpose our data in rows var rows = ml.data.query.Query.transposeQueryData(data); // get our column headings var head = []; ml.each(rows[0], function(k,v) { head.push(k); }); rows.unshift(head); data=rows; var table = ml.$("<table/>").addClass('CSSTableGenerator'); ml.$.each(data, function(rowIndex, r) { var row = ml.$("<tr/>"); ml.$.each(r, function(colIndex, c) { var content = "<p>"+c+"</p>"; row.append(ml.$("<t"+(rowIndex == 0 ? "h" : "d")+"/>").html(content)); }); table.append(row); }); return container.append(table); } }); </script> </head> <body> <div id="results" style="width:100%;height:100%;"></div> </body> </html>
<html> <head> <script type="text/javascript" src="/JS"></script> <script type="text/javascript"> ml.onload(function() { // initialize variables for paging var currentPage = 1, startPosition = 0, recordsPerRequest = 10; // use jQuery for button clicks ml.$('#previousPage').click(function(e) { if (currentPage > 1) { currentPage = currentPage - 1; startPosition = startPosition + recordsPerRequest; // process the query executeQuery(); // update our page number ml.$('#pageNumber').text(currentPage); } }); ml.$('#nextPage').click(function(e) { currentPage = currentPage + 1; startPosition = startPosition + recordsPerRequest; // process the query executeQuery(); // update our page number ml.$('#pageNumber').text(currentPage); }); // Execute our query to get the first page of data executeQuery(); // create a function to encapsulate the query function executeQuery() { // create our query object var q = ml.query(); // select data from the 'hms/hotels' table q.select('CityName').select('HotelName').select('StarRating'); q.from('hms/hotels'); // how many records per request q.take(recordsPerRequest); // set our starting record q.start(startPosition); // let's control the order using our aggregated field q.orderby('CityName'); // execute our query, capture results with the callback function q.run(function(results) { // let's hand off the results for display.... makeTable(ml.$('#results'), results.data ); }); } /****************************************** Helper Function to Layout the Data ******************************************/ function makeTable(container, data) { // let's transpose our data in rows var rows = ml.data.query.Query.transposeQueryData(data); // get our column headings var head = []; ml.each(rows[0], function(k,v) { head.push(k); }); rows.unshift(head); data=rows; var table = ml.$("<table/>").addClass('CSSTableGenerator'); ml.$.each(data, function(rowIndex, r) { var row = ml.$("<tr/>"); ml.$.each(r, function(colIndex, c) { var content = "<p>"+c+"</p>"; row.append(ml.$("<t"+(rowIndex == 0 ? "h" : "d")+"/>").html(content)); }); table.append(row); }); return container.html(table); } }); </script> </head> <body> <div id="results" style="width:100%;"></div> <div style="width:25%;margin:15px auto;"> <button id="previousPage" style="float:left;margin-right:20px"> Previous </button> <div style="display:inline-block"> <strong>Page <span id="pageNumber">1</span></strong> </div> <button id="nextPage" style="float:right"> Next </button> </div> </body> </html>
<html> <head> <script type="text/javascript" src="/JS"></script> <script type="text/javascript"> ml.onload(function() { // create our query object var q = ml.query(); // select data from the 'hms/hotels' table q.select('HotelName').select('CityName').select('StarRating'); q.from('hms/hotels'); // narrow down our example using GeoQuery - this Circle is defined by its center point and radius q.where('XY', 'Contains', 'WKT(CIRCLE(-91.45019397139549 44.87144275016589,285283)),COL(XY)'); // execute our query, capture results with the callback function q.run(function(results) { // let's hand off the results for display.... makeTable(ml.$('#results'), results.data ); }); /****************************************** Helper Function to Layout the Data ******************************************/ function makeTable(container, data) { // let's transpose our data in rows var rows = ml.data.query.Query.transposeQueryData(data); // get our column headings var head = []; ml.each(rows[0], function(k,v) { head.push(k); }); rows.unshift(head); data=rows; var table = ml.$("<table/>").addClass('CSSTableGenerator'); ml.$.each(data, function(rowIndex, r) { var row = ml.$("<tr/>"); ml.$.each(r, function(colIndex, c) { var content = "<p>"+c+"</p>"; row.append(ml.$("<t"+(rowIndex == 0 ? "h" : "d")+"/>").html(content)); }); table.append(row); }); return container.append(table); } }); </script> </head> <body> <div id="results" style="width:100%;height:100%;"></div> </body> </html>
<html> <head> <script type="text/javascript" src="/JS"></script> <script type="text/javascript"> ml.onload(function() { // create our map and hold a reference to it var map=ml.map(document.getElementById('mapdiv')); // define our initial query to send in for GeoQuery processing var query=ml.query().select('HotelName').select('CityName').select('StarRating'); query.from('hms/hotels').take(1000); // RegionSelect options object // (map) [REQUIRED] reference to map // (callback) [REQUIRED] // (drawingType) [OPTIONAL default circle] either rectangle or circle // (query) [OPTIONAL] If provided it will return an ml.query data set to the callback // (table) [OPTIONAL] table to query using the drawing // (take) [OPTIONAL default 1,000] number of rows to return from table query // (query) [OPTIONAL] reference to a configured ml.query var RegionSelectOptions = { map: map, drawingType: 'circle', query: { query: query }, callback: function(data) { // data returned will be Data JSON result from ml.query // empty our map container and destroy our map ml.$('#mapdiv').empty(); map = null; // remove our button ml.$('button').remove(); // display our geoQuery results. makeTable(ml.$('#mapdiv'), data.data) } }; // ml.ui.map.RegionSelect takes one parameter, its Option object var drawCircleForWkt = new ml.ui.map.RegionSelect(RegionSelectOptions); // the beginDrawing() function triggers the drawing capabilities on the map. // this is reusable and can be called as many times as needed. ml.$('.ml-btn').on('click', function(e) { drawCircleForWkt.beginDrawing(); }); /****************************************** Helper Function to Layout the Data ******************************************/ function makeTable(container, data) { // let's transpose our data in rows var rows = ml.data.query.Query.transposeQueryData(data); // get our column headings var head = []; ml.each(rows[0], function(k,v) { head.push(k); }); rows.unshift(head); data=rows; var table = ml.$("<table/>").addClass('CSSTableGenerator'); ml.$.each(data, function(rowIndex, r) { var row = ml.$("<tr/>"); ml.$.each(r, function(colIndex, c) { var content = "<p>"+c+"</p>"; row.append(ml.$("<t"+(rowIndex == 0 ? "h" : "d")+"/>").html(content)); }); table.append(row); }); return container.append(table); } }); </script> <style> .wkt-response { display:none; background-color:white; padding:15px; border:1px solid lightgrey; border-radius:12px; position:absolute; top:10%; left:10%; width:50%; } .mapdiv { width:100%; height:100%; } .ml-btn { position:absolute; top:10px; left:45px; } </style> </head> <body> <div id='mapdiv' class='mapdiv'></div> <button class="ml-btn ml-btn-primary" id="region-select-trigger"> Select a Region </button> <div class='wkt-response'></div> </body> </html>