Skip to content

Commit c5d625b

Browse files
chore: added support of a keyword for terms
1 parent f3a097b commit c5d625b

File tree

17 files changed

+1596
-702
lines changed

17 files changed

+1596
-702
lines changed

package.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@
77
"main": "dist/index.js",
88
"types": "dist/index.d.ts",
99
"scripts": {
10-
"tsc": "node node_modules/typescript/bin/tsc",
11-
"test": "jest --config=./jest.config.json",
10+
"test": "jest --config=./jest.config.json --pathPattern=src/*",
1211
"build:package": "yarn tsc --declaration --project tsconfig.build.json",
1312
"build:replace-tspaths": "yarn tscpaths -p tsconfig.build.json -s ./src -o ./dist",
1413
"build": "rimraf dist && yarn build:package && yarn build:replace-tspaths",
1514
"generate:random-data": "yarn ts-node ./src/test/scripts/generate-random-data.ts",
16-
"es:seed": "yarn ts-node ./src/test/scripts/es-seed.ts"
15+
"es:seed": "yarn ts-node --project tsconfig.json ./src/test/scripts/es-seed.ts"
1716
},
1817
"keywords": [
1918
"nestjs",
@@ -30,6 +29,9 @@
3029
},
3130
"devDependencies": {
3231
"@faker-js/faker": "^8.1.0",
32+
"@nestjs/core": "10.2.7",
33+
"@nestjs/platform-express": "10.2.7",
34+
"@nestjs/testing": "10.2.7",
3335
"@propertyguru/eslint-config-propertyguru": "1.9.0",
3436
"@types/jest": "29.5.5",
3537
"@types/node": "20.8.0",
@@ -54,8 +56,11 @@
5456
"jest": "29.7.0",
5557
"prettier": "3.0.3",
5658
"rimraf": "5.0.1",
59+
"rxjs": "7.8.1",
60+
"supertest": "6.3.3",
5761
"ts-jest": "29.1.1",
5862
"ts-node": "10.9.1",
63+
"tsconfig-paths": "4.2.0",
5964
"tscpaths": "0.0.9",
6065
"typescript": "5.2.2"
6166
}

src/lib/elasticsearch/request.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ export type SearchOptions<TDocument extends Document> = {
66
body?: SearchRequestBody<TDocument>
77
}
88

9-
export type SearchRequest = {
9+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
10+
export type SearchRequest<TDocument extends Document> = {
1011
index: string
1112
}
1213

@@ -16,7 +17,7 @@ export type SearchRequestBody<TDocument extends Document> = {
1617
aggregations?: Record<string, any>
1718
}
1819

19-
export const getSearchRequest = <TDocument extends Document>(index: string, options: SearchOptions<TDocument>): SearchRequest & SearchOptions<TDocument> => ({
20+
export const getSearchRequest = <TDocument extends Document>(index: string, options: SearchOptions<TDocument>): SearchRequest<TDocument> & SearchOptions<TDocument> => ({
2021
index,
2122
...options
2223
})

src/lib/elasticsearch/response.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
1+
import { ApiResponse } from '@elastic/elasticsearch'
2+
import { HitsMetadata } from '@elastic/elasticsearch/api/types'
13
import { Document } from 'lib/types'
24
import { SearchRequest } from './request'
35

4-
export const getSearchResponse = <TDocument extends Document>(request: SearchRequest<TDocument>) => () => ({
5-
records: [],
6-
aggregations: []
7-
})
6+
export type ElasticsearchResult<TDocument extends Document> = {
7+
hits: HitsMetadata<TDocument>
8+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
9+
aggregations?: Record<string, any>
10+
}
11+
12+
export const getSearchResponse = <TDocument extends Document>(request: SearchRequest<TDocument>) => ({ body }: ApiResponse<ElasticsearchResult<TDocument>>) => ({
13+
documents: body.hits.hits.map(({ _source: document }) => document),
14+
aggregations: body.aggregations,
15+
request,
16+
body
17+
})

src/lib/queries/get-term.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Document, Field, FieldType } from 'lib/types'
1+
import { Document, Field, FieldType, Keyword } from 'lib/types'
22

33
export type TermQueryBody<TDocument extends Document, TField extends Field<TDocument>> = {
44
[Key in keyof TDocument]?: { value: FieldType<TDocument, TField> }
@@ -10,7 +10,7 @@ export type TermQuery<TDocument extends Document, TField extends Field<TDocument
1010
}
1111

1212
// eslint-disable-next-line @typescript-eslint/no-explicit-any
13-
export const getTermQuery = <TDocument extends Document, TField extends Field<TDocument> = keyof TDocument>
14-
(field: TField, value: FieldType<TDocument, TField>): TermQuery<TDocument, TField> => ({
13+
export const getTermQuery = <TDocument extends Document, TField extends keyof TDocument = keyof TDocument>
14+
(field: Keyword<TDocument, TField>, value: FieldType<TDocument, TField>): TermQuery<TDocument, TField> => ({
1515
term: { [field]: { value } } as TermQueryBody<TDocument, TField>
1616
})

src/lib/queries/get-terms.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Document, Field, FieldType } from 'lib/types'
1+
import { Document, Field, FieldType, Keyword } from 'lib/types'
22

33
type TermsQueryBody<TDocument extends Document, TField extends Field<TDocument>> = {
44
[Key in keyof TDocument]: Array<FieldType<TDocument, TField>>
@@ -11,6 +11,6 @@ export type TermsQuery<TDocument extends Document, TField extends Field<TDocumen
1111

1212
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1313
export const getTermsQuery = <TDocument extends Document, TField extends Field<TDocument> = keyof TDocument>
14-
(field: TField, values: Array<FieldType<TDocument, TField>>): TermsQuery<TDocument, TField> => ({
14+
(field: Keyword<TDocument, TField>, values: Array<FieldType<TDocument, TField>>): TermsQuery<TDocument, TField> => ({
1515
terms: { [field]: values } as TermsQueryBody<TDocument, TField>
1616
})

src/lib/queries/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
export * from './types'
21
export * from './get-term'
32
export * from './get-terms'
43
export * from './get-must'

src/lib/types/common.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ export type Document = Record<string, any>
66

77
export type Field<TDocument extends Document> = keyof TDocument
88
export type FieldType<TDocument extends Document, TKey extends Field<TDocument>> = TKey extends Field<TDocument> ? TDocument[TKey] : never
9+
export type Keyword<TDocument extends Document, TField extends Field<TDocument>> = TField | `${TField & string}.keyword`

src/nestjs/elasticsearch.service.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Injectable } from '@nestjs/common'
22
import { ElasticsearchService as ElasticsearchBaseService } from '@nestjs/elasticsearch'
33
import { ClassConstructor, Document } from 'lib/types'
4-
import { SearchOptions, getSearchRequest, getSearchResponse } from 'lib/elasticsearch'
4+
import { ElasticsearchResult, SearchOptions, getSearchRequest, getSearchResponse } from 'lib/elasticsearch'
55
import { Catalog } from './injectables'
66
import { ELASTICSEARCH_CATALOG_NAME } from 'lib/constants'
77

@@ -32,8 +32,8 @@ export class ElasticsearchService {
3232

3333
const request = getSearchRequest<TDocument>(index, options)
3434

35-
return this.elasticsearchBaseService.search(request)
36-
.then(getSearchResponse(request))
35+
return this.elasticsearchBaseService.search<ElasticsearchResult<TDocument>>(request)
36+
.then(getSearchResponse<TDocument>(request))
3737
.catch(error => {
3838
console.error(error)
3939

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { setupNestApplication } from 'test/toolkit'
2+
import { ElasticsearchModule } from 'nestjs/elasticsearch.module'
3+
import { ElasticsearchService } from 'nestjs/elasticsearch.service'
4+
import { HomeDocument, PropertyType } from 'test/module'
5+
import { getBoolQuery, getTermQuery } from 'lib/queries'
6+
7+
describe('Making a search', () => {
8+
const { app } = setupNestApplication({
9+
imports: [
10+
ElasticsearchModule.register({
11+
node: 'http://localhost:9200'
12+
})
13+
]
14+
})
15+
16+
it('has service available', () => {
17+
const service = app.get(ElasticsearchService)
18+
19+
expect(service).toBeDefined()
20+
})
21+
22+
it('makes a test search query', async () => {
23+
const service = app.get(ElasticsearchService)
24+
const result = await service.search(HomeDocument, {
25+
size: 10,
26+
body: {
27+
query: getBoolQuery({
28+
must: [
29+
getTermQuery('propertyType.keyword', PropertyType.Flat)
30+
]
31+
})
32+
}
33+
})
34+
35+
console.log(result.documents)
36+
})
37+
})

src/test/module/homes.catalog.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ export class HomeDocument {
2323
readonly hasProperty: boolean
2424

2525
@IsEnum(PropertyType)
26-
readonly propertyType: PropertyType
26+
@IsOptional()
27+
readonly propertyType?: PropertyType
2728

2829
@IsNumber()
2930
@IsOptional()
@@ -35,5 +36,5 @@ export class HomeDocument {
3536

3637
@IsString()
3738
@IsOptional()
38-
readonly propertyAreaSquaredAsString?: number
39+
readonly propertyAreaSquaredAsString?: string
3940
}

0 commit comments

Comments
 (0)