import type { HasReferenceQueryParams , SearchOperator } from './query_params' ; export function getReferencesFilter ( { references , operator = 'OR' , maxTermsPerClause = 1000 , } ) { if ( operator === 'AND' ) { return { bool : { must : references . map ( getNestedTermClauseForReference ) , } , } ; } else { return { bool : { should : getAggregatedTermsClauses ( references , maxTermsPerClause ) , minimum_should_match : 1 , } , } ; } } const getAggregatedTermsClauses = ( references , maxTermsPerClause ) => { const refTypeToIds = references . reduce ( ( map , { type , id } ) => { const ids = map . get ( type ) ?? [ ] ; map . set ( type , [ ... ids , id ] ) ; return map ; } , new Map < string , string [ ] > ( ) ) ; const typeIdChunks = [ ... refTypeToIds . entries ( ) ] . flatMap ( ( [ type , ids ] ) => { return createChunks ( ids , maxTermsPerClause ) . map ( ( chunkIds ) => ( { type , ids : chunkIds } ) ) ; } ) ; return typeIdChunks . map ( ( { type , ids } ) => getNestedTermsClausesForReferences ( type , ids ) ) ; } ; const createChunks = < T > ( array , chunkSize ) : T [ ] [ ] => { const chunks = [ ] ; for ( let i = 0 , len = array . length ; i < len ; i += chunkSize ) chunks . push ( array . slice ( i , i + chunkSize ) ) ; return chunks ; } ; export const getNestedTermClauseForReference = ( reference ) => { return { nested : { path : 'references' , query : { bool : { must : [ { term : { 'references.id' : reference . id , } , } , { term : { 'references.type' : reference . type , } , } , ] , } , } , } , } ; } ; const getNestedTermsClausesForReferences = ( type , ids ) => { return { nested : { path : 'references' , query : { bool : { must : [ { terms : { 'references.id' : ids , } , } , { term : { 'references.type' : type , } , } , ] , } , } , } , } ; } ;