Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add runtime mappings support via addRuntimeMapping() #132

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion docs/Searching/Search.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ var interest = searchBuilder.execute().getHits().map( (document) => document.get

### Runtime Fields

Elasticsearch also allows the creation of runtime fields, which are fields defined in the index mapping but populated at search time via a script.
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).

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


### Define Runtime Fields At Search Time

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.

```js
searchBuilder.addRuntimeMapping( "hasPricing", {
"type" : "boolean",
"script": {
"source": "doc.containsKey( 'price' )"
}
} );
```

Using `.addField()` ensures the field is returned with the document upon query completion:

```js
searchBuilder.addRuntimeMapping( "hasPricing", ... ).addField( "hasPricing" );
```

We can then retrieve the result field via the `getFields()` method:

```js
var documentsWithPricing = searchBuilder.execute()
.getHits()
.filter( (document) => document.getFields()["hasPricing"] );
```

or inlined with the document mento using `hit.getDocument( includeFields = true )`.

### Advanced Query DSL

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.
Expand Down
30 changes: 30 additions & 0 deletions models/SearchBuilder.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ component accessors="true" {
*/
property name="scriptFields" type="struct";

/**
* Property containing elasticsearch "runtime_mappings" definition for runtime scripted fields
*
* https://www.elastic.co/guide/en/elasticsearch/reference/current/runtime-mapping-fields.html
*/
property name="runtimeMappings" type="struct";

/**
* Property containing "fields" array of fields to return for each hit
*
Expand Down Expand Up @@ -1247,6 +1254,10 @@ component accessors="true" {
dsl[ "script_fields" ] = variables.scriptFields;
}

if ( !isNull( variables.runtimeMappings ) ) {
dsl[ "runtime_mappings" ] = variables.runtimeMappings;
}

if ( !isNull( variables.fields ) ) {
dsl[ "fields" ] = variables.fields;
}
Expand Down Expand Up @@ -1362,4 +1373,23 @@ component accessors="true" {
return this;
}


/**
* Append a search-time (runtime) mapping to the search.
*
* @name Name of the runtime mapping field
*
* @script Script to use. `{ "script" : { "lang": "painless", "source" : } }`
*/
public SearchBuilder function addRuntimeMapping(
required string name,
struct script
){
if ( isNull( variables.runtimeMappings ) ) {
variables.runtimeMappings = {};
}
variables.runtimeMappings[ arguments.name ] = arguments.script;
return this;
}

}
14 changes: 14 additions & 0 deletions test-harness/tests/specs/unit/SearchBuilderTest.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,20 @@ component extends="coldbox.system.testing.BaseTestCase" {
expect( searchBuilder.getDSL()[ "script_fields" ] ).toHaveKey( "with5PercentDiscount" );
} );

it( "Tests the addRuntimeMapping() method", function(){
var searchBuilder = variables.model.new( variables.testIndexName, "testdocs" );

searchBuilder.addRuntimeMapping( "hasPricing", {
"type" : "boolean",
"script": {
"source": "doc.containsKey( 'price' )"
}
} );

expect( searchBuilder.getDSL() ).toBeStruct().toHaveKey( "runtime_mappings" );
expect( searchBuilder.getDSL()[ "runtime_mappings" ] ).toHaveKey( "hasPricing" );
} );

it( "Tests the addField() method for retrieving runtime or other fields", function(){
var search = variables.model.new( variables.testIndexName, "testdocs" );

Expand Down
Loading