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

Multilingual search #651

Merged
merged 5 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
3 changes: 2 additions & 1 deletion conf/default.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ geonetwork4_api_url = "/geonetwork/srv/api"
proxy_path = ""
# This optional parameter defines, in which language metadata should be queried in elasticsearch.
# Use ISO 639-2/B (https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) format to indicate the language of the metadata.
# Setting to "current" will use the current language of the Datahub, the UI langage.
fgravin marked this conversation as resolved.
Show resolved Hide resolved
# If not indicated, a wildcard is used and no language preference is applied for the search.
# metadata_language = "fre"
# metadata_language = "fre" or "current"
fgravin marked this conversation as resolved.
Show resolved Hide resolved
# This optional URL should point to the login page that allows authentication to the datahub.
# If not indicated, the default geonetwork login page is used.
# The following three placeholders can be part of this URL:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { ElasticsearchService } from './elasticsearch.service'
import { ES_FIXTURE_AGGS_RESPONSE } from '@geonetwork-ui/common/fixtures'
import { EsSearchParams } from '../types/elasticsearch.model'
import { LangService } from '@geonetwork-ui/util/i18n'
import { EsSearchParams } from '@geonetwork-ui/api/metadata-converter'

const langServiceMock = {
iso3: 'eng',
} as LangService

describe('ElasticsearchService', () => {
let service: ElasticsearchService
let searchFilters

beforeEach(() => {
service = new ElasticsearchService('fre')
service = new ElasticsearchService(langServiceMock, 'fre')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a testBed here would make the test more readable I think, as it would be clear what are the injected dependencies (currently the test manipulates the service properties directly inc. private ones)

})

it('should be created', () => {
Expand Down Expand Up @@ -356,6 +361,47 @@
})
})

describe('#injectLangInQueryStringFields - Search language', () => {
const queryStringFields = ['resourceTitleObject.${searchLang}']
describe('When no lang from config', () => {
beforeEach(() => {
service['metadataLang'] = undefined
})
it('use * wildcard', () => {
expect(
service['injectLangInQueryStringFields'](queryStringFields)[0].split(
'.'
)[1]
).toEqual('*')
})
})
describe('When one lang in config', () => {
beforeEach(() => {
service['metadataLang'] = 'fre'
})
it('search in the config language', () => {
expect(
service['injectLangInQueryStringFields'](queryStringFields)[0].split(
'.'
)[1]
).toEqual('langfre')
})
})
describe('When "current" language from config"', () => {
beforeEach(() => {
service['metadataLang'] = 'current'
service['lang3'] = 'eng'
})
it('search in the UI language', () => {
expect(
service['injectLangInQueryStringFields'](queryStringFields)[0].split(
'.'
)[1]
).toEqual('langeng')
})
})
})

describe('#buildAutocompletePayload', () => {
describe('given an autocomplete config', () => {
it('returns the search payload', () => {
Expand Down Expand Up @@ -659,7 +705,7 @@
expect(
service.parseAggregationResult(
ES_FIXTURE_AGGS_RESPONSE['tag.default'],
{ type: 'terms' } as any

Check warning on line 708 in libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.spec.ts

View workflow job for this annotation

GitHub Actions / Format check, lint, unit tests

Unexpected any. Specify a different type
)
).toStrictEqual({
buckets: [
Expand Down Expand Up @@ -696,7 +742,7 @@
expect(
service.parseAggregationResult(
ES_FIXTURE_AGGS_RESPONSE['availableInServices'],
{ type: 'filters' } as any

Check warning on line 745 in libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.spec.ts

View workflow job for this annotation

GitHub Actions / Format check, lint, unit tests

Unexpected any. Specify a different type
)
).toStrictEqual({
buckets: [
Expand Down Expand Up @@ -776,7 +822,7 @@
expect(
service.parseAggregationResult(
ES_FIXTURE_AGGS_RESPONSE['resolutionScaleDenominator'],
{ type: 'histogram' } as any

Check warning on line 825 in libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.spec.ts

View workflow job for this annotation

GitHub Actions / Format check, lint, unit tests

Unexpected any. Specify a different type
)
).toStrictEqual(expectedHistogram)
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
SortParams,
TermsAggregationResult,
} from '@geonetwork-ui/api/metadata-converter'
import { LangService } from '@geonetwork-ui/util/i18n'

@Injectable({
providedIn: 'root',
Expand All @@ -27,8 +28,10 @@ export class ElasticsearchService {
// runtime fields are computed using a Painless script
// see: https://www.elastic.co/guide/en/elasticsearch/reference/current/runtime-mapping-fields.html
private runtimeFields: Record<string, string> = {}
private lang3 = this.langService.iso3

constructor(
private langService: LangService,
@Optional() @Inject(METADATA_LANGUAGE) private metadataLang: string
) {}

Expand Down Expand Up @@ -167,11 +170,12 @@ export class ElasticsearchService {
return fields.map((field) => ({ [field[1]]: field[0] }))
}

private injectLangInQueryStringFields(
queryStringFields: string[],
lang: string
) {
const queryLang = lang ? `lang${lang}` : `*`
private injectLangInQueryStringFields(queryStringFields: string[]) {
const queryLang = this.metadataLang
? this.metadataLang === 'current'
? `lang${this.lang3}`
: `lang${this.metadataLang}`
: `*`
return queryStringFields.map((field) => {
return field.replace(/\$\{searchLang\}/g, queryLang)
})
Expand Down Expand Up @@ -203,10 +207,7 @@ export class ElasticsearchService {
query_string: {
query: this.escapeSpecialCharacters(any),
default_operator: 'AND',
fields: this.injectLangInQueryStringFields(
ES_QUERY_STRING_FIELDS,
this.metadataLang
),
fields: this.injectLangInQueryStringFields(ES_QUERY_STRING_FIELDS),
},
})
}
Expand Down Expand Up @@ -290,15 +291,12 @@ export class ElasticsearchService {
multi_match: {
query,
type: 'bool_prefix',
fields: this.injectLangInQueryStringFields(
[
'resourceTitleObject.${searchLang}',
'resourceAbstractObject.${searchLang}',
'tag',
'resourceIdentifier',
],
this.metadataLang
),
fields: this.injectLangInQueryStringFields([
'resourceTitleObject.${searchLang}',
'resourceAbstractObject.${searchLang}',
'tag',
'resourceIdentifier',
]),
},
},
],
Expand Down
Loading