Elasticsearch(versions 6.x and 7.x) datasource connector for Loopback 3.x.
lib
directory has the entire source code for this connector
node_modules
folder when you run npm install loopback-connector-esv6 --save --save-exact
examples
directory has a loopback app which uses this connector
node_modules
folder!examples/server/datasources.json
file is there for this demo app to use<yourApp>/server/datasources.json
or <yourApp>/server/datasources.<env>.js
if you want and edit it there but don't start editing the files inside examples/server
itself and expect changes to take place in your app!test
directory has unit tests
examples
folder.npmignore
if you're still confused about what's part of the published connector and what's not.datasources.json
files in this repo mention various configurations:
elasticsearch-ssl
elasticsearch-plain
db
elasticsearch-plain
and then move on to configuring the additional properties that are exemplified in elasticsearch-ssl
. You can mix & match if you'd like to have mongo and es and memory, all three! These are basics of the "connector" framework in loooback and not something we added.model-config.json
file and point the models at the dataSource
you want to use.cd <yourApp>
npm install loopback-connector-esv6 --save --save-exact
docType
property is automatically added in mapping properties which is required to differentiate documents stored in index with loopback model data. It stores loopback modelName value. docType: { type: "keyword", index: true }
eg: shakespeare
.eg: version: 7
basedata
. Required only for version: 6mappingType
1.Edit datasources.json and set:
"elastic-search-ssl": {
"name": "elasticsearch-example-index-datasource",
"connector": "esv6",
"version": 7,
"index": "example-index",
"configuration": { // Elastic client configuration
"node": "http://localhost:9200",
"requestTimeout": 30000,
"pingTimeout": 3000,
"auth": {
"username": "test",
"password": "test"
},
"ssl": {
"rejectUnauthorized": true
}
},
"defaultSize": 50,
"indexSettings": { // Elastic index settings
"number_of_shards": 2,
"number_of_replicas": 1
},
"mappingType": "basedata", // not required for version: 7, will be ignored
"mappingProperties": {
"docType": {
"type": "keyword",
"index": true
},
"id": {
"type": "keyword",
"index": true
},
"seq": {
"type": "integer",
"index": true
},
"name": {
"type": "keyword",
"index": true
},
"email": {
"type": "keyword",
"index": true
},
"birthday": {
"type": "date",
"index": true
},
"role": {
"type": "keyword",
"index": true
},
"order": {
"type": "integer",
"index": true
},
"vip": {
"type": "boolean",
"index": true
},
"objectId": {
"type": "keyword",
"index": true
},
"ttl": {
"type": "integer",
"index": true
},
"created": {
"type": "date",
"index": true
}
}
}
2.You can peek at /examples/server/datasources.json
for more hints.
search_after
feature of elasticsearch is supported in loopback filter._search_after
with loopback type ["any"]
. This field cannot be updated using in connector.sort
value will return in this field._search_after
value in searchafter
key of loopback filter.find
.{
"where": {
"username": "hello"
},
"order": "created DESC",
"searchafter": [
1580902552905
],
"limit": 4
}
[
{
"id": "1bb2dd63-c7b9-588e-a942-15ca4f891a80",
"username": "test",
"_search_after": [
1580902552905
],
"created": "2020-02-05T11:35:52.905Z"
},
{
"id": "fd5ea4df-f159-5816-9104-22147f2a740f",
"username": "test3",
"_search_after": [
1580902552901
],
"created": "2020-02-05T11:35:52.901Z"
},
{
"id": "047c0adb-13ea-5f80-a772-3d2a4691d47a",
"username": "test4",
"_search_after": [
1580902552897
],
"created": "2020-02-05T11:35:52.897Z"
}
]
total
value from elasticsearch for search queries is now supported in loopback response._total_count
with loopback type "number"
. This field cannot be updated using in connector.find
.[
{
"id": "1bb2dd63-c7b9-588e-a942-15ca4f891a80",
"username": "test",
"_search_after": [
1580902552905
],
"_total_count": 3,
"created": "2020-02-05T11:35:52.905Z"
},
{
"id": "fd5ea4df-f159-5816-9104-22147f2a740f",
"username": "test3",
"_search_after": [
1580902552901
],
"_total_count": 3,
"created": "2020-02-05T11:35:52.901Z"
},
{
"id": "047c0adb-13ea-5f80-a772-3d2a4691d47a",
"username": "test4",
"_search_after": [
1580902552897
],
"_total_count": 3,
"created": "2020-02-05T11:35:52.897Z"
}
]
examples
directory contains a loopback app which uses this connector.elasticsearch-ssl
and elasticsearch-plain
in your datasources.json
file? You just need one of them (not both), based on how you've setup your ES instance.model-config.json
to point at the datasource you configured? Maybe you are using a different or misspelled name than what you thought you had!version
elasticsearch
sub-dependency from <yourApp>/node_modules/loopback-connector-esv6/node_modules
folder and then install the latest client:
cd <yourApp>/node_modules/loopback-connector-esv6/node_modules
es6
&& es7
folder
rm -rf es6 es7
npm install
cd <yourApp>
master
into develop
... if they are behind, before starting the feature
branchfeature
branches from the develop
branchfeature
into develop
then create a release
branch to:
npm-release x.x.x -m "<some comment>"
release
into both master
and develop
master
and develop
to GitHubdevelop
branch, if possiblemaster
branch ... I understand and I can't stop you. I only hope that there is a good reason like develop
not being up-to-date with master
for the work you want to build upon.npm-release <versionNumber> -m <commit message>
may be used to publish. Pubilshing to NPM should happen from the master
branch. It should ideally only happen when there is something release worthy. There's no point in publishing just because of changes to test
or examples
folder or any other such entities that aren't part of the "published module" (refer to .npmignore
) to begin with.DEBUG=elasticsearch
for elastic client logs.DEBUG=loopback:connector:elasticsearch
01
or 02
etc. in order to run them in that order by leveraging default alphabetical sorting.02.basic-querying.test.js
file uses two models to test various CRUD operations that any connector must provide, like find(), findById(), findByIds(), updateAttributes()
etc.
User
and Customer
test/resource/datasource-test.json
before
block that performs setup in 02.basic-querying.test.js
file ... these are the equivalent of a MyModel.json
in your real loopback app.
id
for the model and if its generated or not_id
. Without some sort of es-field-level-scripting-on-index (if that is possible at all) ... I am not sure how we could ask elasticsearch to take over auto-generating an id-like value for any arbitrary field! So the connector is setup such that adding id: {type: String, generated: true, id: true}
will tell it to use _id
as the actual field backing the id
... you can keep using the doing model.id
abstraction and in the background _id
values are mapped to it.generated: true
and id: true
?
_id
field inside this connector ... I am not sure if this is the right thing to do. If you had objectId: {type: String, generated: true, id: true}
then you won't find a real objectId
field in your ES documents. Would that be ok? Wouldn't that confuse developers who want to write custom queries and run 3rd party app against their ES instance? Don't use objectId
, use _id
would have to be common knowledge. Is that ok?