Initial commit

This commit is contained in:
Luka Romih
2022-12-07 04:43:36 +01:00
commit 257f3c354f
496 changed files with 55373 additions and 0 deletions
@@ -0,0 +1,40 @@
// TODO Consider alternative paging when hits exceed 10000.
module.exports = function (filters, hitsPerPage, page) {
const queryDsl = {
from: hitsPerPage * (page - 1),
size: hitsPerPage,
query: {
bool: {
filter: []
}
},
sort: ['_score', 'timeCreated']
}
if (filters.status) {
queryDsl.query.bool.filter.push({
term: {
status: filters.status
}
})
}
if (filters.assignedConsultant) {
queryDsl.query.bool.filter.push({
term: {
'assignedConsultants.id': filters.assignedConsultant
}
})
}
if (filters.primaryDomain) {
queryDsl.query.bool.filter.push({
term: {
'primaryDomain.id': filters.primaryDomain
}
})
}
return queryDsl
}
@@ -0,0 +1,76 @@
// TODO Consider alternative paging when hits exceed 10000.
module.exports = function (searchString, filters, hitsPerPage, page) {
const queryDsl = {
from: hitsPerPage * (page - 1),
size: hitsPerPage,
query: {
bool: {
must: {
dis_max: {
queries: [
{
constant_score: {
filter: {
match_phrase: {
title: searchString
}
},
boost: 3
}
},
{
constant_score: {
filter: {
match_phrase: {
question: searchString
}
},
boost: 2
}
},
{
constant_score: {
filter: {
match_phrase: {
answer: searchString
}
},
boost: 1
}
}
]
}
},
filter: []
}
},
sort: ['_score', 'timeCreated']
}
if (filters.status) {
queryDsl.query.bool.filter.push({
term: {
status: filters.status
}
})
}
if (filters.assignedConsultant) {
queryDsl.query.bool.filter.push({
term: {
'assignedConsultants.id': filters.assignedConsultant
}
})
}
if (filters.primaryDomain) {
queryDsl.query.bool.filter.push({
term: {
'primaryDomain.id': filters.primaryDomain
}
})
}
return queryDsl
}
@@ -0,0 +1,70 @@
const { queryForField } = require('../..')
const whitespace = /\s+/
// TODO Consider alternative paging when hits exceed 10000.
module.exports = function (searchString, filters, hitsPerPage, page) {
const searchTokens = searchString.split(whitespace)
const queryDsl = {
from: hitsPerPage * (page - 1),
size: hitsPerPage,
query: {
bool: {
must: {
dis_max: {
queries: [
{
constant_score: {
filter: queryForField('title', searchTokens),
boost: 3
}
},
{
constant_score: {
filter: queryForField('question', searchTokens),
boost: 2
}
},
{
constant_score: {
filter: queryForField('answer', searchTokens),
boost: 1
}
}
]
}
},
filter: []
}
},
sort: ['_score', 'timeCreated']
}
if (filters.status) {
queryDsl.query.bool.filter.push({
term: {
status: filters.status
}
})
}
if (filters.assignedConsultant) {
queryDsl.query.bool.filter.push({
term: {
'assignedConsultants.id': filters.assignedConsultant
}
})
}
if (filters.primaryDomain) {
queryDsl.query.bool.filter.push({
term: {
'primaryDomain.id': filters.primaryDomain
}
})
}
return queryDsl
}
@@ -0,0 +1,85 @@
// TODO Consider alternative paging when hits exceed 10000.
module.exports = function (searchString, filters, hitsPerPage, page) {
const queryDsl = {
from: hitsPerPage * (page - 1),
size: hitsPerPage,
query: {
bool: {
must: {
dis_max: {
queries: [
{
constant_score: {
filter: {
match: {
title: {
query: searchString,
operator: 'and'
}
}
},
boost: 3
}
},
{
constant_score: {
filter: {
match: {
question: {
query: searchString,
operator: 'and'
}
}
},
boost: 2
}
},
{
constant_score: {
filter: {
match: {
answer: {
query: searchString,
operator: 'and'
}
}
},
boost: 1
}
}
]
}
},
filter: []
}
},
sort: ['_score', 'timeCreated']
}
if (filters.status) {
queryDsl.query.bool.filter.push({
term: {
status: filters.status
}
})
}
if (filters.assignedConsultant) {
queryDsl.query.bool.filter.push({
term: {
'assignedConsultants.id': filters.assignedConsultant
}
})
}
if (filters.primaryDomain) {
queryDsl.query.bool.filter.push({
term: {
'primaryDomain.id': filters.primaryDomain
}
})
}
return queryDsl
}
@@ -0,0 +1,129 @@
const { EDITOR_MAX_HITS } = require('../../../../../config/settings')
module.exports = function (dictionaryId, filters, searchFieldFilters) {
const queryDsl = {
_source: ['id', 'isValid', 'isPublished', 'term'],
fields: ['foreignEntries.terms'],
script_fields: {
commentActivityIndicator: {
script: {
source: `
if (!doc.containsKey('timeMostRecentComment') || doc['timeMostRecentComment'].empty) return "";
ZonedDateTime mostRecentCommentTime = doc['timeMostRecentComment'].value;
long nowMilli = params['now'];
Instant nowInstant = Instant.ofEpochMilli(nowMilli);
ZonedDateTime now = ZonedDateTime.ofInstant(nowInstant, ZoneId.of('Z'));
long ageInDays = ChronoUnit.DAYS.between(mostRecentCommentTime, now);
if (ageInDays < 7) {
return "T"
} else if (ageInDays < 30) {
return "M"
} else if (ageInDays < 365) {
return "L"
} else {
return ""
}
`,
params: {
now: Date.now()
}
}
}
},
size: EDITOR_MAX_HITS,
query: {
bool: {
filter: [
{
term: {
'dictionary.id': dictionaryId
}
}
]
}
},
sort: ['term.sort', 'homonymSort']
}
if (searchFieldFilters) queryDsl.query.bool.filter.push(searchFieldFilters)
if (filters) {
if (filters.isValid !== undefined) {
queryDsl.query.bool.filter.push({
term: {
isValid: filters.isValid
}
})
}
if (filters.isPublished !== undefined) {
queryDsl.query.bool.filter.push({
term: {
isPublished: filters.isPublished
}
})
}
if (filters.hasComments !== undefined) {
if (filters.hasComments === true) {
queryDsl.query.bool.filter.push({
exists: {
field: 'timeMostRecentComment'
}
})
} else {
queryDsl.query.bool.filter.push({
bool: {
must_not: {
exists: {
field: 'timeMostRecentComment'
}
}
}
})
}
}
if (filters.isComplete !== undefined) {
if (filters.isComplete === true) {
queryDsl.query.bool.filter.push({
term: {
status: 'complete'
}
})
} else {
queryDsl.query.bool.filter.push({
bool: {
must_not: {
term: {
status: 'complete'
}
}
}
})
}
}
if (filters.isTerminologyReviewed !== undefined) {
queryDsl.query.bool.filter.push({
term: {
isTerminologyReviewed: filters.isTerminologyReviewed
}
})
}
if (filters.isLanguageReviewed !== undefined) {
queryDsl.query.bool.filter.push({
term: {
isLanguageReviewed: filters.isLanguageReviewed
}
})
}
}
return queryDsl
}
@@ -0,0 +1,103 @@
const { fieldMap } = require('../..')
const generateQuery = require('./all')
module.exports = function (dictionaryId, searchField, filters) {
const searchFieldFilters = generateSearchFieldFilters(searchField)
const queryDsl = generateQuery(dictionaryId, filters, searchFieldFilters)
return queryDsl
}
function generateSearchFieldFilters(searchField) {
const mappedName = fieldMap[searchField]
if (mappedName) {
if (mappedName.startsWith('foreignEntries')) {
return {
nested: {
path: 'foreignEntries',
query: {
exists: {
field: mappedName
}
}
}
}
}
return {
exists: {
field: mappedName
}
}
}
return {
dis_max: {
queries: [
{
exists: {
field: 'term'
}
},
{
exists: {
field: 'synonyms'
}
},
{
exists: {
field: 'label'
}
},
{
exists: {
field: 'definition'
}
},
{
exists: {
field: 'other'
}
},
{
exists: {
field: 'domainLabels'
}
},
{
exists: {
field: 'links'
}
},
{
nested: {
path: 'foreignEntries',
query: {
dis_max: {
queries: [
{
exists: {
field: 'foreignEntries.terms'
}
},
{
exists: {
field: 'foreignEntries.synonyms'
}
},
{
exists: {
field: 'foreignEntries.definition'
}
}
]
}
}
}
}
]
}
}
}
@@ -0,0 +1,76 @@
const { fieldMap } = require('../..')
const generateQuery = require('./all')
module.exports = function (dictionaryId, searchField, searchString, filters) {
const searchFieldFilters = generateSearchFieldFilters(
searchField,
searchString
)
const queryDsl = generateQuery(dictionaryId, filters, searchFieldFilters)
return queryDsl
}
function generateSearchFieldFilters(searchField, searchString) {
const mappedName = fieldMap[searchField]
if (mappedName) {
if (mappedName.startsWith('foreignEntries')) {
return {
nested: {
path: 'foreignEntries',
query: {
match_phrase: {
[mappedName]: searchString
}
}
}
}
}
return {
match_phrase: {
[mappedName]: searchString
}
}
}
return {
dis_max: {
queries: [
{
multi_match: {
query: searchString,
type: 'phrase',
fields: [
'term',
'synonyms',
'label',
'definition',
'other',
'domainLabels',
'links'
]
}
},
{
nested: {
path: 'foreignEntries',
query: {
multi_match: {
query: searchString,
type: 'phrase',
fields: [
'foreignEntries.terms',
'foreignEntries.synonyms',
'foreignEntries.definition'
]
}
}
}
}
]
}
}
}
@@ -0,0 +1,62 @@
const { fieldMap, queryForField } = require('../..')
const generateQuery = require('./all')
const whitespace = /\s+/
module.exports = function (dictionaryId, searchField, searchString, filters) {
const searchFieldFilters = generateSearchFieldFilters(
searchField,
searchString
)
const queryDsl = generateQuery(dictionaryId, filters, searchFieldFilters)
return queryDsl
}
function generateSearchFieldFilters(searchField, searchString) {
const searchTokens = searchString.split(whitespace)
const mappedName = fieldMap[searchField]
if (mappedName) {
if (mappedName.startsWith('foreignEntries')) {
return {
nested: {
path: 'foreignEntries',
query: queryForField(mappedName, searchTokens)
}
}
}
return queryForField(mappedName, searchTokens)
}
return {
dis_max: {
queries: [
queryForField('term', searchTokens),
queryForField('synonyms', searchTokens),
queryForField('label', searchTokens),
queryForField('definition', searchTokens),
queryForField('other', searchTokens),
queryForField('domainLabels', searchTokens),
queryForField('links', searchTokens),
{
nested: {
path: 'foreignEntries',
query: {
dis_max: {
queries: [
queryForField('foreignEntries.terms', searchTokens),
queryForField('foreignEntries.synonyms', searchTokens),
queryForField('foreignEntries.definition', searchTokens)
]
}
}
}
}
]
}
}
}
@@ -0,0 +1,82 @@
const { fieldMap } = require('../..')
const generateQuery = require('./all')
module.exports = function (dictionaryId, searchField, searchString, filters) {
const searchFieldFilters = generateSearchFieldFilters(
searchField,
searchString
)
const queryDsl = generateQuery(dictionaryId, filters, searchFieldFilters)
return queryDsl
}
function generateSearchFieldFilters(searchField, searchString) {
const mappedName = fieldMap[searchField]
if (mappedName) {
if (mappedName.startsWith('foreignEntries')) {
return {
nested: {
path: 'foreignEntries',
query: {
match: {
[mappedName]: {
query: searchString,
operator: 'and'
}
}
}
}
}
}
return {
match: {
[mappedName]: {
query: searchString,
operator: 'and'
}
}
}
}
return {
dis_max: {
queries: [
{
multi_match: {
query: searchString,
operator: 'and',
fields: [
'term',
'synonyms',
'label',
'definition',
'other',
'domainLabels',
'links'
]
}
},
{
nested: {
path: 'foreignEntries',
query: {
multi_match: {
query: searchString,
operator: 'and',
fields: [
'foreignEntries.terms',
'foreignEntries.synonyms',
'foreignEntries.definition'
]
}
}
}
}
]
}
}
}
@@ -0,0 +1,183 @@
const debug = require('debug')('termPortal:generate-query')
const genAllHitQuery = require('./main/all')
const genAllAggQuery = require('./main/aggregate-all')
const genPhraseHitQuery = require('./main/phrase')
const genPhraseAggQuery = require('./main/aggregate-phrase')
const genWildcardHitQuery = require('./main/wildcard')
const genWildcardAggQuery = require('./main/aggregate-wildcard')
const genMultiWordHitQuery = require('./main/word-multi')
const genWordAggQuery = require('./main/aggregate-word')
const genSingleWordHitQuery = require('./main/word-single')
const genEditorAllQuery = require('./editor/all')
const genEditorExistsQuery = require('./editor/exists')
const genEditorPhraseQuery = require('./editor/phrase')
const genEditorWildcardQuery = require('./editor/wildcard')
const genEditorWordsQuery = require('./editor/words')
const genConsultancyAllQuery = require('./consultancy/all')
const genConsultancyPhraseQuery = require('./consultancy/phrase')
const genConsultancyWildcardQuery = require('./consultancy/wildcard')
const genConsultancyWordsQuery = require('./consultancy/words')
const notOnlyAsterisks = /[^*"\s]/
const hasWildcards = /[*?]/
const hasWhitespace = /\s/
// Determines query type, constructs and returns appropriate search engine query(es).
exports.main = async (
searchString,
filters,
hitsPerPage,
page,
withAggregation
) => {
let hitsQuery
let aggregateQuery
const firstChar = searchString[0]
const lastChar = searchString[searchString.length - 1]
// TODO Aditional sanitization/transformation?
if (!notOnlyAsterisks.test(searchString)) {
debug('query type: all')
hitsQuery = genAllHitQuery(filters, hitsPerPage, page)
if (withAggregation) {
aggregateQuery = genAllAggQuery(hitsQuery)
}
} else if (firstChar === '"' && lastChar === '"') {
debug('query type: phrase')
searchString = searchString.slice(1, -1)
hitsQuery = await genPhraseHitQuery(
searchString,
filters,
hitsPerPage,
page
)
if (withAggregation) {
aggregateQuery = genPhraseAggQuery(searchString, hitsQuery)
}
} else if (hasWildcards.test(searchString)) {
debug('query type: wildcard')
let slovenianFieldQueries, foreignFieldQueries
;[hitsQuery, slovenianFieldQueries, foreignFieldQueries] =
await genWildcardHitQuery(searchString, filters, hitsPerPage, page)
if (withAggregation) {
aggregateQuery = genWildcardAggQuery(
hitsQuery,
slovenianFieldQueries,
foreignFieldQueries
)
}
} else if (hasWhitespace.test(searchString)) {
debug('query type: multi word')
hitsQuery = await genMultiWordHitQuery(
searchString,
filters,
hitsPerPage,
page
)
if (withAggregation) {
aggregateQuery = genWordAggQuery(searchString, hitsQuery)
}
} else {
debug('query type: single word')
hitsQuery = await genSingleWordHitQuery(
searchString,
filters,
hitsPerPage,
page
)
if (withAggregation) {
aggregateQuery = genWordAggQuery(searchString, hitsQuery)
}
}
return withAggregation ? [hitsQuery, aggregateQuery] : hitsQuery
}
// Determines query type, constructs and returns appropriate search engine query for editor.
exports.editor = (dictionaryId, searchField, searchString, filters) => {
let hitsQuery
const firstChar = searchString[0]
const lastChar = searchString[searchString.length - 1]
// TODO Aditional sanitization/transformation?
if (!searchString) {
debug('query type: all')
hitsQuery = genEditorAllQuery(dictionaryId, filters)
} else if (!notOnlyAsterisks.test(searchString)) {
debug('query type: exists')
hitsQuery = genEditorExistsQuery(dictionaryId, searchField, filters)
} else if (firstChar === '"' && lastChar === '"') {
debug('query type: phrase')
searchString = searchString.slice(1, -1)
hitsQuery = genEditorPhraseQuery(
dictionaryId,
searchField,
searchString,
filters
)
} else if (hasWildcards.test(searchString)) {
debug('query type: wildcard')
hitsQuery = genEditorWildcardQuery(
dictionaryId,
searchField,
searchString,
filters
)
} else {
debug('query type: words')
hitsQuery = genEditorWordsQuery(
dictionaryId,
searchField,
searchString,
filters
)
}
return hitsQuery
}
// Determines query type, constructs and returns appropriate search engine query for consultancy.
exports.consultancy = (searchString, filters, hitsPerPage, page) => {
let hitsQuery
const firstChar = searchString[0]
const lastChar = searchString[searchString.length - 1]
// TODO Aditional sanitization/transformation?
if (!notOnlyAsterisks.test(searchString)) {
debug('query type: all')
hitsQuery = genConsultancyAllQuery(filters, hitsPerPage, page)
} else if (firstChar === '"' && lastChar === '"') {
debug('query type: phrase')
searchString = searchString.slice(1, -1)
hitsQuery = genConsultancyPhraseQuery(
searchString,
filters,
hitsPerPage,
page
)
} else if (hasWildcards.test(searchString)) {
debug('query type: wildcard')
hitsQuery = genConsultancyWildcardQuery(
searchString,
filters,
hitsPerPage,
page
)
} else {
debug('query type: words')
hitsQuery = genConsultancyWordsQuery(
searchString,
filters,
hitsPerPage,
page
)
}
return hitsQuery
}
@@ -0,0 +1,42 @@
module.exports = function (hitsQuery) {
// A shallow copy will prevent hitsQuery from being modified.
const queryDsl = { ...hitsQuery }
queryDsl.from = 0
queryDsl.size = 0
queryDsl.aggs = {
primaryDomains: {
terms: {
field: 'primaryDomain.id',
size: 100
}
},
dictionaries: {
terms: {
field: 'dictionary.id',
size: 200
}
},
sources: {
terms: {
field: 'source.code'
}
},
foreign: {
nested: {
path: 'foreignEntries'
},
aggs: {
targetLanguages: {
terms: {
field: 'foreignEntries.lang.id',
size: 50
}
}
}
}
}
return queryDsl
}
@@ -0,0 +1,80 @@
module.exports = function (searchString, hitsQuery) {
// A shallow copy will prevent hitsQuery from being modified.
const queryDsl = { ...hitsQuery }
queryDsl.from = 0
queryDsl.size = 0
queryDsl.aggs = {
primaryDomains: {
terms: {
field: 'primaryDomain.id',
size: 100
}
},
dictionaries: {
terms: {
field: 'dictionary.id',
size: 200
}
},
sources: {
terms: {
field: 'source.code'
}
},
slovenianHits: {
filter: {
multi_match: {
query: searchString,
type: 'phrase',
fields: [
'term',
'synonyms',
'label',
'definition',
'other',
'domainLabels',
'links'
]
}
}
},
foreign: {
nested: {
path: 'foreignEntries'
},
aggs: {
targetLanguages: {
terms: {
field: 'foreignEntries.lang.id',
size: 50
}
},
foreignHits: {
filter: {
multi_match: {
query: searchString,
type: 'phrase',
fields: [
'foreignEntries.terms',
'foreignEntries.synonyms',
'foreignEntries.definition'
]
}
},
aggs: {
sourceLanguages: {
terms: {
field: 'foreignEntries.lang.id',
size: 50
}
}
}
}
}
}
}
return queryDsl
}
@@ -0,0 +1,68 @@
module.exports = function (
hitsQuery,
slovenianFieldQueries,
foreignFieldQueries
) {
// A shallow copy will prevent hitsQuery from being modified.
const queryDsl = { ...hitsQuery }
queryDsl.from = 0
queryDsl.size = 0
queryDsl.aggs = {
primaryDomains: {
terms: {
field: 'primaryDomain.id',
size: 100
}
},
dictionaries: {
terms: {
field: 'dictionary.id',
size: 200
}
},
sources: {
terms: {
field: 'source.code'
}
},
slovenianHits: {
filter: {
dis_max: {
queries: slovenianFieldQueries
}
}
},
foreign: {
nested: {
path: 'foreignEntries'
},
aggs: {
targetLanguages: {
terms: {
field: 'foreignEntries.lang.id',
size: 50
}
},
foreignHits: {
filter: {
dis_max: {
queries: foreignFieldQueries
}
},
aggs: {
sourceLanguages: {
terms: {
field: 'foreignEntries.lang.id',
size: 50
}
}
}
}
}
}
}
return queryDsl
}
@@ -0,0 +1,80 @@
module.exports = function (searchString, hitsQuery) {
// A shallow copy will prevent hitsQuery from being modified.
const queryDsl = { ...hitsQuery }
queryDsl.from = 0
queryDsl.size = 0
queryDsl.aggs = {
primaryDomains: {
terms: {
field: 'primaryDomain.id',
size: 100
}
},
dictionaries: {
terms: {
field: 'dictionary.id',
size: 200
}
},
sources: {
terms: {
field: 'source.code'
}
},
slovenianHits: {
filter: {
multi_match: {
query: searchString,
operator: 'and',
fields: [
'term',
'synonyms',
'label',
'definition',
'other',
'domainLabels',
'links'
]
}
}
},
foreign: {
nested: {
path: 'foreignEntries'
},
aggs: {
targetLanguages: {
terms: {
field: 'foreignEntries.lang.id',
size: 50
}
},
foreignHits: {
filter: {
multi_match: {
query: searchString,
operator: 'and',
fields: [
'foreignEntries.terms',
'foreignEntries.synonyms',
'foreignEntries.definition'
]
}
},
aggs: {
sourceLanguages: {
terms: {
field: 'foreignEntries.lang.id',
size: 50
}
}
}
}
}
}
}
return queryDsl
}
@@ -0,0 +1,64 @@
// TODO Consider alternative paging when hits exceed 10000.
module.exports = function (filters, hitsPerPage, page) {
const queryDsl = {
from: hitsPerPage * (page - 1),
size: hitsPerPage,
query: {
bool: {
filter: [
{
term: {
isPublished: true
}
},
{
term: {
'dictionary.status': 'published'
}
}
]
}
},
sort: ['_score', 'term.sort', 'homonymSort']
}
if (filters.primaryDomains.length) {
queryDsl.query.bool.filter.push({
terms: {
'primaryDomain.id': filters.primaryDomains
}
})
}
if (filters.dictionaries.length) {
queryDsl.query.bool.filter.push({
terms: {
'dictionary.id': filters.dictionaries
}
})
}
if (filters.sources.length) {
queryDsl.query.bool.filter.push({
terms: {
'source.code': filters.sources
}
})
}
if (filters.targetLanguages.length) {
queryDsl.query.bool.filter.push({
nested: {
path: 'foreignEntries',
query: {
terms: {
'foreignEntries.lang.id': filters.targetLanguages
}
}
}
})
}
return queryDsl
}
@@ -0,0 +1,247 @@
const { separateSlovenianLanguage } = require('../..')
// TODO Consider alternative paging when hits exceed 10000.
module.exports = async function (searchString, filters, hitsPerPage, page) {
const queryDsl = {
from: hitsPerPage * (page - 1),
size: hitsPerPage,
query: {
bool: {
must: {
dis_max: {
queries: [
{
constant_score: {
filter: {
term: {
'term.keyword': {
value: searchString
}
}
},
boost: 6
}
},
{
constant_score: {
filter: {
match_phrase: {
term: searchString
}
},
boost: 5
}
},
{
constant_score: {
filter: {
nested: {
path: 'foreignEntries',
query: {
term: {
'foreignEntries.terms.keyword': {
value: searchString
}
}
}
}
},
boost: 4
}
},
{
constant_score: {
filter: {
nested: {
path: 'foreignEntries',
query: {
match_phrase: {
'foreignEntries.terms': searchString
}
}
}
},
boost: 3
}
},
{
constant_score: {
filter: {
dis_max: {
queries: [
{
match_phrase: {
synonyms: searchString
}
},
{
nested: {
path: 'foreignEntries',
query: {
match_phrase: {
'foreignEntries.synonyms': searchString
}
}
}
}
]
}
},
boost: 2
}
},
{
constant_score: {
filter: {
dis_max: {
queries: [
{
multi_match: {
query: searchString,
type: 'phrase',
fields: [
'label',
'definition',
'other',
'domainLabels',
'links'
]
}
},
{
nested: {
path: 'foreignEntries',
query: {
match_phrase: {
'foreignEntries.definition': searchString
}
}
}
}
]
}
},
boost: 1
}
}
]
}
},
filter: [
{
term: {
isPublished: true
}
},
{
term: {
'dictionary.status': 'published'
}
}
]
}
},
sort: ['_score', 'term.sort', 'homonymSort']
}
if (filters.primaryDomains.length) {
queryDsl.query.bool.filter.push({
terms: {
'primaryDomain.id': filters.primaryDomains
}
})
}
if (filters.dictionaries.length) {
queryDsl.query.bool.filter.push({
terms: {
'dictionary.id': filters.dictionaries
}
})
}
if (filters.sources.length) {
queryDsl.query.bool.filter.push({
terms: {
'source.code': filters.sources
}
})
}
if (filters.targetLanguages.length) {
queryDsl.query.bool.filter.push({
nested: {
path: 'foreignEntries',
query: {
terms: {
'foreignEntries.lang.id': filters.targetLanguages
}
}
}
})
}
if (filters.sourceLanguages.length) {
const [foreignLanguages, isSlovenianSource] =
await separateSlovenianLanguage(filters.sourceLanguages)
const sourceLanguageFilter = {
dis_max: {
queries: []
}
}
if (isSlovenianSource) {
sourceLanguageFilter.dis_max.queries.push({
multi_match: {
query: searchString,
type: 'phrase',
fields: [
'term',
'synonyms',
'label',
'definition',
'other',
'domainLabels',
'links'
]
}
})
}
if (foreignLanguages.length) {
sourceLanguageFilter.dis_max.queries.push({
nested: {
path: 'foreignEntries',
query: {
bool: {
must: [
{
terms: {
'foreignEntries.lang.id': foreignLanguages
}
},
{
multi_match: {
query: searchString,
type: 'phrase',
fields: [
'foreignEntries.terms',
'foreignEntries.synonyms',
'foreignEntries.definition'
]
}
}
]
}
}
}
})
}
queryDsl.query.bool.filter.push(sourceLanguageFilter)
}
return queryDsl
}
@@ -0,0 +1,207 @@
const { separateSlovenianLanguage, queryForField } = require('../..')
const whitespace = /\s+/
// TODO Consider alternative paging when hits exceed 10000.
module.exports = async function (searchString, filters, hitsPerPage, page) {
const searchTokens = searchString.split(whitespace)
const termQuery = queryForField('term', searchTokens)
const foreignTermQuery = queryForField('foreignEntries.terms', searchTokens)
const synonymsQuery = queryForField('synonyms', searchTokens)
const foreignSynonymsQuery = queryForField(
'foreignEntries.synonyms',
searchTokens
)
const labelQuery = queryForField('label', searchTokens)
const definitionQuery = queryForField('definition', searchTokens)
const otherQuery = queryForField('other', searchTokens)
const domainLabelsQuery = queryForField('domainLabels', searchTokens)
const linksQuery = queryForField('links', searchTokens)
const foreignDefinitionQuery = queryForField(
'foreignEntries.definition',
searchTokens
)
const slovenianFieldQueries = [
termQuery,
synonymsQuery,
labelQuery,
definitionQuery,
otherQuery,
domainLabelsQuery,
linksQuery
]
const foreignFieldQueries = [
foreignTermQuery,
foreignSynonymsQuery,
foreignDefinitionQuery
]
const queryDsl = {
from: hitsPerPage * (page - 1),
size: hitsPerPage,
query: {
bool: {
must: {
dis_max: {
queries: [
{
constant_score: {
filter: termQuery,
boost: 5
}
},
{
constant_score: {
filter: {
nested: {
path: 'foreignEntries',
query: foreignTermQuery
}
},
boost: 3
}
},
{
constant_score: {
filter: {
dis_max: {
queries: [
synonymsQuery,
{
nested: {
path: 'foreignEntries',
query: foreignSynonymsQuery
}
}
]
}
},
boost: 2
}
},
{
constant_score: {
filter: {
dis_max: {
queries: [
labelQuery,
definitionQuery,
otherQuery,
domainLabelsQuery,
linksQuery,
{
nested: {
path: 'foreignEntries',
query: foreignDefinitionQuery
}
}
]
}
},
boost: 1
}
}
]
}
},
filter: [
{
term: {
isPublished: true
}
},
{
term: {
'dictionary.status': 'published'
}
}
]
}
},
sort: ['_score', 'term.sort', 'homonymSort']
}
if (filters.primaryDomains.length) {
queryDsl.query.bool.filter.push({
terms: {
'primaryDomain.id': filters.primaryDomains
}
})
}
if (filters.dictionaries.length) {
queryDsl.query.bool.filter.push({
terms: {
'dictionary.id': filters.dictionaries
}
})
}
if (filters.sources.length) {
queryDsl.query.bool.filter.push({
terms: {
'source.code': filters.sources
}
})
}
if (filters.targetLanguages.length) {
queryDsl.query.bool.filter.push({
nested: {
path: 'foreignEntries',
query: {
terms: {
'foreignEntries.lang.id': filters.targetLanguages
}
}
}
})
}
if (filters.sourceLanguages.length) {
const [foreignLanguages, isSlovenianSource] =
await separateSlovenianLanguage(filters.sourceLanguages)
const sourceLanguageFilter = {
dis_max: {
queries: []
}
}
if (isSlovenianSource) {
sourceLanguageFilter.dis_max.queries.push(...slovenianFieldQueries)
}
if (foreignLanguages.length) {
sourceLanguageFilter.dis_max.queries.push({
nested: {
path: 'foreignEntries',
query: {
bool: {
must: [
{
terms: {
'foreignEntries.lang.id': foreignLanguages
}
},
{
dis_max: {
queries: foreignFieldQueries
}
}
]
}
}
}
})
}
queryDsl.query.bool.filter.push(sourceLanguageFilter)
}
return [queryDsl, slovenianFieldQueries, foreignFieldQueries]
}
@@ -0,0 +1,233 @@
const { separateSlovenianLanguage } = require('../..')
// TODO Consider alternative paging when hits exceed 10000.
module.exports = async function (searchString, filters, hitsPerPage, page) {
const queryDsl = {
from: hitsPerPage * (page - 1),
size: hitsPerPage,
query: {
bool: {
must: {
dis_max: {
queries: [
{
constant_score: {
filter: {
match: {
term: {
query: searchString,
operator: 'and'
}
}
},
boost: 5
}
},
{
constant_score: {
filter: {
nested: {
path: 'foreignEntries',
query: {
match: {
'foreignEntries.terms': {
query: searchString,
operator: 'and'
}
}
}
}
},
boost: 3
}
},
{
constant_score: {
filter: {
dis_max: {
queries: [
{
match: {
synonyms: {
query: searchString,
operator: 'and'
}
}
},
{
nested: {
path: 'foreignEntries',
query: {
match: {
'foreignEntries.synonyms': {
query: searchString,
operator: 'and'
}
}
}
}
}
]
}
},
boost: 2
}
},
{
constant_score: {
filter: {
dis_max: {
queries: [
{
multi_match: {
query: searchString,
operator: 'and',
fields: [
'label',
'definition',
'other',
'domainLabels',
'links'
]
}
},
{
nested: {
path: 'foreignEntries',
query: {
match: {
'foreignEntries.definition': {
query: searchString,
operator: 'and'
}
}
}
}
}
]
}
},
boost: 1
}
}
]
}
},
filter: [
{
term: {
isPublished: true
}
},
{
term: {
'dictionary.status': 'published'
}
}
]
}
},
sort: ['_score', 'term.sort', 'homonymSort']
}
if (filters.primaryDomains.length) {
queryDsl.query.bool.filter.push({
terms: {
'primaryDomain.id': filters.primaryDomains
}
})
}
if (filters.dictionaries.length) {
queryDsl.query.bool.filter.push({
terms: {
'dictionary.id': filters.dictionaries
}
})
}
if (filters.sources.length) {
queryDsl.query.bool.filter.push({
terms: {
'source.code': filters.sources
}
})
}
if (filters.targetLanguages.length) {
queryDsl.query.bool.filter.push({
nested: {
path: 'foreignEntries',
query: {
terms: {
'foreignEntries.lang.id': filters.targetLanguages
}
}
}
})
}
if (filters.sourceLanguages.length) {
const [foreignLanguages, isSlovenianSource] =
await separateSlovenianLanguage(filters.sourceLanguages)
const sourceLanguageFilter = {
dis_max: {
queries: []
}
}
if (isSlovenianSource) {
sourceLanguageFilter.dis_max.queries.push({
multi_match: {
query: searchString,
operator: 'and',
fields: [
'term',
'synonyms',
'label',
'definition',
'other',
'domainLabels',
'links'
]
}
})
}
if (foreignLanguages.length) {
sourceLanguageFilter.dis_max.queries.push({
nested: {
path: 'foreignEntries',
query: {
bool: {
must: [
{
terms: {
'foreignEntries.lang.id': foreignLanguages
}
},
{
multi_match: {
query: searchString,
operator: 'and',
fields: [
'foreignEntries.terms',
'foreignEntries.synonyms',
'foreignEntries.definition'
]
}
}
]
}
}
}
})
}
queryDsl.query.bool.filter.push(sourceLanguageFilter)
}
return queryDsl
}
@@ -0,0 +1,262 @@
const { separateSlovenianLanguage } = require('../..')
// TODO Consider alternative paging when hits exceed 10000.
module.exports = async function (searchString, filters, hitsPerPage, page) {
const queryDsl = {
from: hitsPerPage * (page - 1),
size: hitsPerPage,
query: {
bool: {
must: {
dis_max: {
queries: [
{
constant_score: {
filter: {
term: {
'term.keyword': {
value: searchString
}
}
},
boost: 6
}
},
{
constant_score: {
filter: {
match: {
term: {
query: searchString,
operator: 'and'
}
}
},
boost: 5
}
},
{
constant_score: {
filter: {
nested: {
path: 'foreignEntries',
query: {
term: {
'foreignEntries.terms.keyword': {
value: searchString
}
}
}
}
},
boost: 4
}
},
{
constant_score: {
filter: {
nested: {
path: 'foreignEntries',
query: {
match: {
'foreignEntries.terms': {
query: searchString,
operator: 'and'
}
}
}
}
},
boost: 3
}
},
{
constant_score: {
filter: {
dis_max: {
queries: [
{
match: {
synonyms: {
query: searchString,
operator: 'and'
}
}
},
{
nested: {
path: 'foreignEntries',
query: {
match: {
'foreignEntries.synonyms': {
query: searchString,
operator: 'and'
}
}
}
}
}
]
}
},
boost: 2
}
},
{
constant_score: {
filter: {
dis_max: {
queries: [
{
multi_match: {
query: searchString,
operator: 'and',
fields: [
'label',
'definition',
'other',
'domainLabels',
'links'
]
}
},
{
nested: {
path: 'foreignEntries',
query: {
match: {
'foreignEntries.definition': {
query: searchString,
operator: 'and'
}
}
}
}
}
]
}
},
boost: 1
}
}
]
}
},
filter: [
{
term: {
isPublished: true
}
},
{
term: {
'dictionary.status': 'published'
}
}
]
}
},
sort: ['_score', 'term.sort', 'homonymSort']
}
if (filters.primaryDomains.length) {
queryDsl.query.bool.filter.push({
terms: {
'primaryDomain.id': filters.primaryDomains
}
})
}
if (filters.dictionaries.length) {
queryDsl.query.bool.filter.push({
terms: {
'dictionary.id': filters.dictionaries
}
})
}
if (filters.sources.length) {
queryDsl.query.bool.filter.push({
terms: {
'source.code': filters.sources
}
})
}
if (filters.targetLanguages.length) {
queryDsl.query.bool.filter.push({
nested: {
path: 'foreignEntries',
query: {
terms: {
'foreignEntries.lang.id': filters.targetLanguages
}
}
}
})
}
if (filters.sourceLanguages.length) {
const [foreignLanguages, isSlovenianSource] =
await separateSlovenianLanguage(filters.sourceLanguages)
const sourceLanguageFilter = {
dis_max: {
queries: []
}
}
if (isSlovenianSource) {
sourceLanguageFilter.dis_max.queries.push({
multi_match: {
query: searchString,
operator: 'and',
fields: [
'term',
'synonyms',
'label',
'definition',
'other',
'domainLabels',
'links'
]
}
})
}
if (foreignLanguages.length) {
sourceLanguageFilter.dis_max.queries.push({
nested: {
path: 'foreignEntries',
query: {
bool: {
must: [
{
terms: {
'foreignEntries.lang.id': foreignLanguages
}
},
{
multi_match: {
query: searchString,
operator: 'and',
fields: [
'foreignEntries.terms',
'foreignEntries.synonyms',
'foreignEntries.definition'
]
}
}
]
}
}
}
})
}
queryDsl.query.bool.filter.push(sourceLanguageFilter)
}
return queryDsl
}