227 lines
6.2 KiB
JavaScript
227 lines
6.2 KiB
JavaScript
const Portal = require('../../portal')
|
|
const { getSlovenianLanguageId } = require('..')
|
|
|
|
const slCollator = new Intl.Collator('sl', { sensitivity: 'base' })
|
|
|
|
// Return a new array, with slovenian language removed and isSlovenianSource set to true if present.
|
|
exports.separateSlovenianLanguage = async languages => {
|
|
const slovenianLanguageId = await getSlovenianLanguageId()
|
|
let isSlovenianSource = false
|
|
|
|
const foreignLanguages = languages.filter(language => {
|
|
if (language !== slovenianLanguageId) return true
|
|
|
|
isSlovenianSource = true
|
|
return false
|
|
})
|
|
|
|
return [foreignLanguages, isSlovenianSource]
|
|
}
|
|
|
|
// Simplify and enhance search engine's hits output into useful entries object.
|
|
exports.prepareEntries = hits => {
|
|
const entriesByCategory = hits.body.hits.hits.reduce(
|
|
(agg, hit) => {
|
|
const entry = hit._source
|
|
|
|
switch (hit._score) {
|
|
case 6:
|
|
case 5:
|
|
agg.byTerm.push(entry)
|
|
break
|
|
case 4:
|
|
case 3:
|
|
agg.byForeignTerm.push(entry)
|
|
break
|
|
case 2:
|
|
case 1:
|
|
agg.byOther.push(entry)
|
|
break
|
|
default:
|
|
agg.uncategorized.push(entry)
|
|
}
|
|
|
|
return agg
|
|
},
|
|
{ byTerm: [], byForeignTerm: [], byOther: [], uncategorized: [] }
|
|
)
|
|
|
|
return entriesByCategory
|
|
}
|
|
|
|
// Transform search engine's aggregation raw output into correct and friendly format.
|
|
exports.prepareAggregation = async (aggregationRaw, determinedLanguage) => {
|
|
const { aggregations, hits } = aggregationRaw.body
|
|
|
|
const hitsCount = hits.total.value
|
|
if (!hitsCount) return
|
|
|
|
const primaryDomainIds = aggregations.primaryDomains.buckets.map(
|
|
bucket => bucket.key
|
|
)
|
|
|
|
const dictionaryIds = aggregations.dictionaries.buckets.map(
|
|
bucket => bucket.key
|
|
)
|
|
|
|
const languageIdSet = new Set()
|
|
const refinedSourceLanguageBuckets = []
|
|
|
|
aggregations.foreign.targetLanguages.buckets.forEach(bucket =>
|
|
languageIdSet.add(bucket.key)
|
|
)
|
|
|
|
const slovenianHitCount = aggregations.slovenianHits?.doc_count
|
|
// "Match all" aggregation returns no slovenian hits and source languages.
|
|
if (slovenianHitCount) {
|
|
const slovenianLanguageId = await getSlovenianLanguageId()
|
|
const slovenianBucket = {
|
|
key: slovenianLanguageId,
|
|
doc_count: slovenianHitCount
|
|
}
|
|
let wasSlovenianBucketInserted = false
|
|
|
|
aggregations.foreign.foreignHits.sourceLanguages.buckets.forEach(bucket => {
|
|
if (!wasSlovenianBucketInserted && bucket.doc_count < slovenianHitCount) {
|
|
languageIdSet.add(slovenianLanguageId)
|
|
refinedSourceLanguageBuckets.push(slovenianBucket)
|
|
wasSlovenianBucketInserted = true
|
|
}
|
|
languageIdSet.add(bucket.key)
|
|
refinedSourceLanguageBuckets.push(bucket)
|
|
})
|
|
|
|
if (!wasSlovenianBucketInserted) {
|
|
languageIdSet.add(slovenianLanguageId)
|
|
refinedSourceLanguageBuckets.push(slovenianBucket)
|
|
}
|
|
} else if (slovenianHitCount === 0) {
|
|
aggregations.foreign.foreignHits.sourceLanguages.buckets.forEach(bucket => {
|
|
languageIdSet.add(bucket.key)
|
|
refinedSourceLanguageBuckets.push(bucket)
|
|
})
|
|
}
|
|
|
|
const languageIds = [...languageIdSet]
|
|
|
|
const names = await Portal.getSearchAggregateNames(
|
|
primaryDomainIds,
|
|
dictionaryIds,
|
|
languageIds,
|
|
determinedLanguage
|
|
)
|
|
|
|
const aggregation = {
|
|
sourceLanguages: refinedSourceLanguageBuckets.map(
|
|
({ key: id, doc_count: hits }) => {
|
|
return { id, name: names.languages[id], hits }
|
|
}
|
|
),
|
|
targetLanguages: aggregations.foreign.targetLanguages.buckets.map(
|
|
({ key: id, doc_count: hits }) => {
|
|
return { id, name: names.languages[id], hits }
|
|
}
|
|
),
|
|
primaryDomains: aggregations.primaryDomains.buckets.map(
|
|
({ key: id, doc_count: hits }) => {
|
|
return { id, name: names.primaryDomains[id], hits }
|
|
}
|
|
),
|
|
dictionaries: aggregations.dictionaries.buckets.map(
|
|
({ key: id, doc_count: hits }) => {
|
|
return { id, name: names.dictionaries[id], hits }
|
|
}
|
|
),
|
|
sources: aggregations.sources.buckets.map(
|
|
({ key: id, doc_count: hits }) => {
|
|
return { id, name: id, hits }
|
|
}
|
|
)
|
|
}
|
|
|
|
sortAggregation(aggregation)
|
|
|
|
return aggregation
|
|
}
|
|
|
|
// Enhance aggregation for display in search filters.
|
|
exports.prepareSeachFilterData = (aggregation, filters) => {
|
|
const enhancedAggregation = {}
|
|
|
|
if (aggregation) {
|
|
for (const category of Object.keys(aggregation)) {
|
|
const enhancedCategoryMembers = aggregation[category].map(member => {
|
|
if (filters[category].includes(member.id)) member.checked = true
|
|
return member
|
|
})
|
|
|
|
enhancedAggregation[category] = enhancedCategoryMembers
|
|
}
|
|
}
|
|
|
|
return enhancedAggregation
|
|
}
|
|
|
|
// Maps editor search api field names into search engine ones.
|
|
exports.fieldMap = {
|
|
term: 'term',
|
|
synonyms: 'synonyms',
|
|
label: 'label',
|
|
definition: 'definition',
|
|
other: 'other',
|
|
domainLabels: 'domainLabels',
|
|
links: 'links',
|
|
foreignTerms: 'foreignEntries.terms',
|
|
foreignSynonyms: 'foreignEntries.synonyms',
|
|
foreignDefinition: 'foreignEntries.definition'
|
|
}
|
|
|
|
// Generate search engine DSL wildcard query fragment for a single field.
|
|
exports.queryForField = (field, searchTokens) => {
|
|
return {
|
|
bool: {
|
|
filter: searchTokens.map(token => {
|
|
return {
|
|
wildcard: {
|
|
[field]: {
|
|
value: token
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
// Simplify and enhance search engine's editor hits output into useful entries list.
|
|
exports.prepareEditorEntries = hits => {
|
|
const entries = hits.body.hits.hits.map(hit => {
|
|
const entry = hit._source
|
|
|
|
entry.foreignTerm = hit.fields['foreignEntries.terms']?.[0]
|
|
entry.commentActivityIndicator = hit.fields.commentActivityIndicator[0]
|
|
|
|
return entry
|
|
})
|
|
|
|
return entries
|
|
}
|
|
|
|
function sortAggregation(aggregation) {
|
|
for (const categoryBuckets of Object.values(aggregation)) {
|
|
categoryBuckets.sort(bucketCompareFn)
|
|
}
|
|
}
|
|
|
|
function bucketCompareFn(bucketA, bucketB) {
|
|
if (bucketA.hits !== bucketB.hits) return 0
|
|
return slCollator.compare(bucketA.name, bucketB.name)
|
|
}
|
|
|
|
// Simplify search engine's consultancy hits output into useful entries list.
|
|
exports.prepareConsultancyEntries = hits => {
|
|
const entries = hits.body.hits.hits.map(hit => hit._source)
|
|
|
|
return entries
|
|
}
|