Skip to content

Commit d55d8cc

Browse files
authored
Merge pull request #132 from michaelborn/feat/add-runtime-mappings-fields
Add runtime mappings support via addRuntimeMapping()
2 parents 5b1f38d + b11e4d2 commit d55d8cc

File tree

3 files changed

+75
-1
lines changed

3 files changed

+75
-1
lines changed

docs/Searching/Search.md

+31-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ var interest = searchBuilder.execute().getHits().map( (document) => document.get
162162

163163
### Runtime Fields
164164

165-
Elasticsearch also allows the creation of runtime fields, which are fields defined in the index mapping but populated at search time via a script.
165+
Elasticsearch also supports defining runtime fields, which are fields defined in the index mapping but populated at search time via a script. You can [define these in the index mapping](../Indices/Managing-Indices.md#creating-runtime-fields), or [define them at search time](#define-runtime-fields-at-search-time).
166166

167167
{% hint style="info" %}
168168
See [Managing-Indices](../Indices/Managing-Indices.md#creating-runtime-fields) for more information on creating runtime fields.
@@ -203,6 +203,36 @@ for( hit in result.getHits() ){
203203
}
204204
```
205205

206+
207+
### Define Runtime Fields At Search Time
208+
209+
Elasticsearch also allows you to [define runtime fields at search time](https://www.elastic.co/guide/en/elasticsearch/reference/current/runtime-search-request.html), and unlike [script fields](#script-fields) these runtime fields are available to use in aggregations, search queries, and so forth.
210+
211+
```js
212+
searchBuilder.addRuntimeMapping( "hasPricing", {
213+
"type" : "boolean",
214+
"script": {
215+
"source": "doc.containsKey( 'price' )"
216+
}
217+
} );
218+
```
219+
220+
Using `.addField()` ensures the field is returned with the document upon query completion:
221+
222+
```js
223+
searchBuilder.addRuntimeMapping( "hasPricing", ... ).addField( "hasPricing" );
224+
```
225+
226+
We can then retrieve the result field via the `getFields()` method:
227+
228+
```js
229+
var documentsWithPricing = searchBuilder.execute()
230+
.getHits()
231+
.filter( (document) => document.getFields()["hasPricing"] );
232+
```
233+
234+
or inlined with the document mento using `hit.getDocument( includeFields = true )`.
235+
206236
### Advanced Query DSL
207237

208238
The SearchBuilder also allows full use of the [Elasticsearch query language](https://www.elastic.co/guide/en/elasticsearch/reference/current/_introducing_the_query_language.html), allowing full configuration of your search queries. There are several methods to provide the raw query language to the Search Builder. One is during instantiation.

models/SearchBuilder.cfc

+30
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ component accessors="true" {
5757
*/
5858
property name="scriptFields" type="struct";
5959

60+
/**
61+
* Property containing elasticsearch "runtime_mappings" definition for runtime scripted fields
62+
*
63+
* https://www.elastic.co/guide/en/elasticsearch/reference/current/runtime-mapping-fields.html
64+
*/
65+
property name="runtimeMappings" type="struct";
66+
6067
/**
6168
* Property containing "fields" array of fields to return for each hit
6269
*
@@ -1247,6 +1254,10 @@ component accessors="true" {
12471254
dsl[ "script_fields" ] = variables.scriptFields;
12481255
}
12491256

1257+
if ( !isNull( variables.runtimeMappings ) ) {
1258+
dsl[ "runtime_mappings" ] = variables.runtimeMappings;
1259+
}
1260+
12501261
if ( !isNull( variables.fields ) ) {
12511262
dsl[ "fields" ] = variables.fields;
12521263
}
@@ -1362,4 +1373,23 @@ component accessors="true" {
13621373
return this;
13631374
}
13641375

1376+
1377+
/**
1378+
* Append a search-time (runtime) mapping to the search.
1379+
*
1380+
* @name Name of the runtime mapping field
1381+
*
1382+
* @script Script to use. `{ "script" : { "lang": "painless", "source" : } }`
1383+
*/
1384+
public SearchBuilder function addRuntimeMapping(
1385+
required string name,
1386+
struct script
1387+
){
1388+
if ( isNull( variables.runtimeMappings ) ) {
1389+
variables.runtimeMappings = {};
1390+
}
1391+
variables.runtimeMappings[ arguments.name ] = arguments.script;
1392+
return this;
1393+
}
1394+
13651395
}

test-harness/tests/specs/unit/SearchBuilderTest.cfc

+14
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,20 @@ component extends="coldbox.system.testing.BaseTestCase" {
830830
expect( searchBuilder.getDSL()[ "script_fields" ] ).toHaveKey( "with5PercentDiscount" );
831831
} );
832832

833+
it( "Tests the addRuntimeMapping() method", function(){
834+
var searchBuilder = variables.model.new( variables.testIndexName, "testdocs" );
835+
836+
searchBuilder.addRuntimeMapping( "hasPricing", {
837+
"type" : "boolean",
838+
"script": {
839+
"source": "doc.containsKey( 'price' )"
840+
}
841+
} );
842+
843+
expect( searchBuilder.getDSL() ).toBeStruct().toHaveKey( "runtime_mappings" );
844+
expect( searchBuilder.getDSL()[ "runtime_mappings" ] ).toHaveKey( "hasPricing" );
845+
} );
846+
833847
it( "Tests the addField() method for retrieving runtime or other fields", function(){
834848
var search = variables.model.new( variables.testIndexName, "testdocs" );
835849

0 commit comments

Comments
 (0)