Michael Born
Web developer at Ortus Solutions
Michael Born
@michaelborn_me
"CFSearch is a 2010 solution to a 2020 problem"
- Michael Born
"Search via relational database is a 2001 solution to a 2020 problem"
- Michael Born
A 2020 solution to a 2020 problem
A CFML wrapper for ElasticSearch to facilitate:
and configuration
docker run -d \
-p 9200:9200 \
-e "discovery.type=single-node" \
--name="myApp_ES" \
elasticsearch:7.5.1
box install cbelasticsearch
// config/Coldbox.cfc
moduleSettings = {
"cbElasticsearch" : {
"hosts" : [ {
"serverProtocol" : "http",
"serverName" : "127.0.0.1",
"serverPort" : "9200"
} ],
"defaultIndex" = "reviews"
}
}
lazy
dog
quick
brown
fox
jumps
over
the
the quick brown fox jumps over the lazy dog
Breaks down keywords into their root
run
running
runners
List of words within a language that are not relevant to most searches
mighty
jungle
in the jungle, the mighty jungle
A definition of fields and field types for a specific index.
{
"mappings" : {
"properties" : {
"primaryTitle" : { "type" : "text" },
"titleType" : { "type" : "keyword" },
"runtime_mins" : { "type" : "integer" },
"startYear" : { "type" : "integer" },
"budget" : { "type" : "integer" },
"box_office_gross" : { "type" : "integer" }
}
}
}
A single record within an index
{
"primaryTitle": "The Fellowship Of The Ring",
"titleType": "movie",
"runtime_mins": "178",
"startYear" : "2001",
"budget" : "93,000,000",
"box_office_gross": "887,800,000"
}
Creation and management
component {
/**
* Initialize the ElasticSearch index on app load/reinit
*/
void function afterConfigurationLoad( event, interceptData ){
// create index...
}
}
function buildMyIndex() {
getInstance( "IndexBuilder@cbElasticsearch" )
.new(
"reviews",
{
"_doc" = {
"_all" = { "enabled" = false },
"properties" = {
"title" = { "type" = "text" },
"authorName" = { "type" = "integer" },
"publishedDate" = { "type" = "text" },
"stars" = { "type" = "keyword" },
"content" = { "type" = "text" }
}
}
}
).save();
}
function createBookIndex() {
getInstance( "IndexBuilder" )
.new( "books", getInstance( "MappingBuilder@cbElasticSearch" )
.create( function( mapping ) {
mapping.text( "title" );
mapping.object( "author", function( mapping ) {
mapping.text( "firstname" );
mapping.text( "lastname" );
} );
} );
} );
}
function insertReview() {
var bookReview = {
"title" : "'Phantom': Lost in Hyperspace",
"authorName" : "Rita Kempley",
"publishedDate" : DateFormat( "1999-05-19" ),
"stars" : "1",
"content" : "The Empire strikes out..."
};
var document = getInstance( "Document@cbElasticsearch" )
.new(
index = "reviews",
type = "_doc",
properties = bookReview
);
document.save();
}
with CBElasticsearch
function searchByTitle( required string title ) {
return getInstance( "SearchBuilder@cbElasticSearch" )
.new( "news" )
.match( "title", arguments.title )
.execute();
}
var results = getInstance( "SearchBuilder@CBelasticsearch" )
.new( "books" )
.filterMatch( "description", "toast" )
.execute();
var results = getInstance( "SearchBuilder@CBelasticsearch" )
.new( "books" )
.match( "description", "toast" )
.execute();
var result = getInstance( "SearchBuilder@cbElasticSearch" )
.new( "reviews")
.term( "stars", 5 )
.execute();
var result = getInstance( "SearchBuilder@cbElasticSearch" )
.new( "reviews" )
.match( "content", "burnt" )
.execute();
var result = getInstance( "SearchBuilder@cbElasticSearch" )
.new( "reviews" )
.mustMatch( "author", "Luis Majano" )
.mustMatch( "content", "star wars" )
.execute();
var result = getInstance( "SearchBuilder@cbElasticSearch" )
.new( "reviews" )
.shouldMatch( "author", "Luis Majano" )
.shouldMatch( "author", "Jon Clausen" )
.execute();
Building a Yelp sample search
Happy to answer any questions in the CBElasticsearch room
By Michael Born
If you think database full-text search is slow and bare-bones, you're right. ElasticSearch is becoming the de-facto standard for lightning-fast search, and with cbElasticSearch, the Ortus-built ElasticSearch API client, you can easily integrate with ElasticSearch in your ColdBox application to provide your users with fast and powerful search.