Initial commit
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
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 => {
|
||||
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
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user