/**
 * Load dependencies
 */ import * as querystring from 'querystring' ; import * as format from './utils/format' ; import * as arrayUtils from './utils/array' ; import * as versionUtils from './utils/version' ; import { Filters , HlOptions , MltOptions , TermsOptions , GroupOptions , FacetOptions , DateOptions , JoinOptions , } from './types' ; import { dateISOify } from './utils/format' ; export type QueryOptions = { solrVersion ? : number ; } ; constructor return { Query } api export class Query { public solrVersion : number | undefined ; public parameters : any [ ] ; constructor ( options ? ) { this . solrVersion = ( options && options . solrVersion ) || undefined ; this . parameters = [ ] ; } param { String } parameter return { Query } api set ( parameter ) { const self = this ; this . parameters . push ( parameter ) ; return self ; } param { String } type return { Query } api defType ( type ) { const self = this ; const parameter = 'defType=' + type ; this . parameters . push ( parameter ) ; return self ; } param { String } name return { Query } api requestHandler ( name ) { const self = this ; const parameter = 'qt=' + name ; this . parameters . push ( parameter ) ; return self ; } qt = Query . prototype . requestHandler ; param { String | Object } q return { Query } api q ( q ) { const self = this ; let parameter = 'q=' ; if ( typeof q === 'string' ) { parameter += encodeURIComponent ( q ) ; } else { parameter += querystring . stringify ( q , '%20AND%20' , ':' ) ; } this . parameters . push ( parameter ) ; return self ; } param { String } op return { Query } api qop ( op ) { const self = this ; let parameter = 'q.op=' ; parameter += op ; this . parameters . push ( parameter ) ; return self ; } param { String } df return { Query } api df ( df ) { const self = this ; let parameter = 'df=' ; parameter += df ; this . parameters . push ( parameter ) ; return self ; } param { Number } start return { Query } api start ( start ) { const self = this ; const parameter = 'start=' + start ; this . parameters . push ( parameter ) ; return self ; } param { Number } rows return { Query } api rows ( rows ) { const self = this ; const parameter = 'rows=' + rows ; this . parameters . push ( parameter ) ; return self ; } param mark cursorMark ( mark = '*' ) { const self = this ; const parameter = 'cursorMark=' + encodeURIComponent ( mark ) ; this . parameters . push ( parameter ) ; return self ; } param { Object } options return { Query } api sort ( options ) { const self = this ; let parameter = 'sort=' ; parameter += querystring . stringify ( options , ',' , '%20' ) ; this . parameters . push ( parameter ) ; return self ; } param { Array | Object } options param { String } options2 . field param { String | Number | Date } options2 . start param { String | Number | Date } options2 . end return { Query } api example rangeFilter ( options ) { const self = this ; const options2 = format . dateISOify ( options ) ; let parameter = 'fq=' ; if ( Array . isArray ( options2 ) ) { parameter += '(' ; const filters = options2 . map ( function ( option ) { const key = option . field ; const startParam = option . start ? option . start . toString ( ) : '*' ; const endParam = option . end ? option . end . toString ( ) : '*' ; const filter = { } ; filter [ key ] = '[' + startParam + '%20TO%20' + endParam + ']' ; return format . stringify ( filter , '' , ':' ) ; } ) ; parameter += filters . join ( '%20AND%20' ) ; parameter += ')' ; } else { const key = options2 . field ; const startParam = options2 . start ? options2 . start . toString ( ) : '*' ; const endParam = options2 . end ? options2 . end . toString ( ) : '*' ; const filter = { } ; filter [ key ] = '[' + startParam + '%20TO%20' + endParam + ']' ; parameter += format . stringify ( filter , '' , ':' ) ; } this . parameters . push ( parameter ) ; return self ; } return { Query } api example joinFilter ( options ) { const self = this ; let parameter = 'fq=' ; const filter = `{!join fromIndex=${ options . fromIndex } from=${ options . from } to=${ options . to } v='${ options . field }:${ options . value }'}` ; parameter += encodeURIComponent ( filter ) ; this . parameters . push ( parameter ) ; return self ; } param { String } field param { String | String [ ] | Number | Number [ ] | Date | Date [ ] } value return { Query } api example matchFilter ( field , value ) { const self = this ; let parameter = 'fq=' ; if ( Array . isArray ( value ) ) { value = value . map ( dateISOify ) ; value = `(${ value . join ( ' OR ' ) })` ; } else { value = format . dateISOify ( value ) ; } parameter += field + ':' + encodeURIComponent ( value ) ; this . parameters . push ( parameter ) ; return self ; } param { Object | Array } filters return { Query } throws api example fq ( filters ) { const self = this ; if ( Array . isArray ( filters ) ) { filters . map ( ( f ) => this . matchFilter ( f . field , f . value ) ) ; return self ; } if ( filters instanceof Object ) return this . matchFilter ( filters . field , filters . value ) ; else { throw new Error ( 'unknown type for filter in fq()' ) ; } } param { String | Array } fields return { Query } api fl ( fields ) { const self = this ; let parameter = 'fl=' ; if ( typeof fields === 'string' ) { parameter += encodeURIComponent ( fields ) ; } else { parameter += encodeURIComponent ( fields . join ( ',' ) ) ; } this . parameters . push ( parameter ) ; return self ; } restrict = Query . prototype . fl ; param { String | Number } time return { Query } api timeout ( time ) { const self = this ; const parameter = 'timeAllowed=' + time ; this . parameters . push ( parameter ) ; return self ; } param { String } field return { Query } api groupBy ( field ) { const self = this ; this . group ( { field : field , } ) ; return self ; } param options param { Boolean } options . on param { String | Array } options . field param { String | Array } options . query param { Number } options . limit param { Number } options . offset param { String } options . sort param { String } options . format param { Boolean } options . main param { Boolean } options . ngroups param { Boolean } options . truncate param { Number } options . cache return { Query } api group ( options ) { const self = this ; if ( options . on === false ) { this . parameters . push ( 'group=false' ) ; } else { this . parameters . push ( 'group=true' ) ; } if ( options . field ) { options . field = arrayUtils . toArray ( options . field ) ; options . field . forEach ( function ( field ) { self . parameters . push ( 'group.field=' + field ) ; } ) ; } if ( options . query ) { if ( ! Array . isArray ( options . query ) ) { options . query = [ options . query ] ; } options . query . forEach ( function ( query ) { self . parameters . push ( 'group.query=' + encodeURIComponent ( query ) ) ; } ) ; } if ( options . limit !== undefined ) { this . parameters . push ( 'group.limit=' + options . limit ) ; } if ( options . offset !== undefined ) { this . parameters . push ( 'group.offset=' + options . offset ) ; } if ( options . sort ) { this . parameters . push ( 'group.sort=' + encodeURIComponent ( options . sort ) ) ; } if ( options . format ) { this . parameters . push ( 'group.format=' + encodeURIComponent ( options . format ) ) ; } if ( options . main !== undefined ) { this . parameters . push ( 'group.main=' + options . main ) ; } if ( options . ngroups !== undefined ) { this . parameters . push ( 'group.ngroups=' + options . ngroups ) ; } if ( options . truncate !== undefined ) { this . parameters . push ( 'group.truncate=' + options . truncate ) ; } if ( options . cache !== undefined ) { this . parameters . push ( 'group.cache.percent=' + options . cache ) ; } return self ; } param options param { Boolean } options . on param { String } options . query param { String | Array } options . field param { String } options . prefix param { String } options . sort param { Number } options . limit param { Number } options . offset param { Number } options . mincount param { Boolean } options . missing param { String } options . method param { String | Array } options . pivot param { String } options . pivot . mincount return { Query } api facet ( options ) { const self = this ; if ( options . on === false ) { this . parameters . push ( 'facet=false' ) ; } else { this . parameters . push ( 'facet=true' ) ; } if ( options . query ) { this . parameters . push ( 'facet.query=' + encodeURIComponent ( options . query ) ) ; } if ( options . field ) { options . field = arrayUtils . toArray ( options . field ) ; options . field . forEach ( function ( field ) { self . parameters . push ( 'facet.field=' + field ) ; } ) ; } if ( options . prefix ) { this . parameters . push ( 'facet.prefix=' + encodeURIComponent ( options . prefix ) ) ; } if ( options . sort ) { this . parameters . push ( 'facet.sort=' + encodeURIComponent ( options . sort ) ) ; } if ( options . limit !== undefined ) { this . parameters . push ( 'facet.limit=' + options . limit ) ; } if ( options . offset !== undefined ) { this . parameters . push ( 'facet.offset=' + options . offset ) ; } if ( options . mincount !== undefined ) { this . parameters . push ( 'facet.mincount=' + options . mincount ) ; } if ( options . missing !== undefined ) { this . parameters . push ( 'facet.missing=' + options . missing ) ; } if ( options . method ) { this . parameters . push ( 'facet.method=' + options . method ) ; } if ( this . solrVersion && versionUtils . version ( this . solrVersion ) >= versionUtils . Solr4_0 ) { if ( options . pivot ) { options . field = arrayUtils . toArray ( options . pivot . fields ) ; options . field . forEach ( function ( field ) { self . parameters . push ( 'facet.pivot=' + field ) ; } ) ; if ( options . pivot . mincount ) { this . parameters . push ( 'facet.pivot.mincount=' + options . pivot . mincount ) ; } } } return self ; } param options param { Boolean } options . on param { String | Array } options . fl param { Number } options . count param { Number } options . mintf param { Number } options . mindf param { Number } options . minwl param { Number } options . maxwl param { Number } options . maxqt param { Number } options . maxntp param { Boolean } options . boost param { String | Object } options . qf return { Query } api mlt ( options ) { let parameter ; const self = this ; if ( options . on === false ) { this . parameters . push ( 'mlt=false' ) ; } else { this . parameters . push ( 'mlt=true' ) ; } if ( options . fl ) { if ( options . fl instanceof Array ) options . fl = options . fl . join ( ',' ) ; this . parameters . push ( 'mlt.fl=' + encodeURIComponent ( options . fl ) ) ; } if ( options . count !== undefined ) { this . parameters . push ( 'mlt.count=' + options . count ) ; } if ( options . mintf !== undefined ) { this . parameters . push ( 'mlt.mintf=' + options . mintf ) ; } if ( options . mindf !== undefined ) { this . parameters . push ( 'mlt.mindf=' + options . mindf ) ; } if ( options . minwl !== undefined ) { this . parameters . push ( 'mlt.minwl=' + options . minwl ) ; } if ( options . maxwl !== undefined ) { this . parameters . push ( 'mlt.maxwl=' + options . maxwl ) ; } if ( options . maxqt !== undefined ) { this . parameters . push ( 'mlt.maxqt=' + options . maxqt ) ; } if ( options . maxntp !== undefined ) { this . parameters . push ( 'mlt.maxntp=' + options . maxntp ) ; } if ( options . boost !== undefined ) { this . parameters . push ( 'mlt.boost=' + options . boost ) ; } if ( options . qf ) { if ( typeof options . qf === 'object' ) { parameter = querystring . stringify ( options . qf , '%20' , '^' ) ; } else { parameter = encodeURIComponent ( options . qf ) ; } this . parameters . push ( 'mlt.qf=' + parameter ) ; } return self ; } return { Query } api dismax ( ) { const self = this ; this . defType ( 'dismax' ) ; return self ; } return { Query } api edismax ( ) { const self = this ; this . defType ( 'edismax' ) ; return self ; } return { Query } api debugQuery ( ) { const self = this ; this . parameters . push ( 'debugQuery=true' ) ; return self ; } param { Object } options return { Query } api example qf ( options ) { const self = this ; let parameter = 'qf=' ; parameter += querystring . stringify ( options , '%20' , '^' ) ; this . parameters . push ( parameter ) ; return self ; } param { String | Number } minimum return { Query } api example mm ( minimum ) { const self = this ; const parameter = 'mm=' + minimum ; this . parameters . push ( parameter ) ; return self ; } param { Object } options return { Query } api pf ( options ) { const self = this ; let parameter = 'pf=' ; parameter += querystring . stringify ( options , '%20' , '^' ) ; this . parameters . push ( parameter ) ; return self ; } param { Number } slop return { Query } api ps ( slop ) { const self = this ; const parameter = 'ps=' + slop ; this . parameters . push ( parameter ) ; return self ; } param { Number } slop return { Query } api qs ( slop ) { const self = this ; const parameter = 'qs=' + slop ; this . parameters . push ( parameter ) ; return self ; } param { Float | Number } tiebreaker return { Query } api tie ( tiebreaker ) { const self = this ; const parameter = 'tie=' + tiebreaker ; this . parameters . push ( parameter ) ; return self ; } param { Object } options return { Query } api bq ( options ) { const self = this ; let parameter = 'bq=' ; parameter += querystring . stringify ( options , '%20' , '^' ) ; this . parameters . push ( parameter ) ; return self ; } param { String } functions return { Query } api bf ( functions ) { const self = this ; const parameter = 'bf=' + functions ; this . parameters . push ( parameter ) ; return self ; } param { String } functions return { Query } api boost ( functions ) { const self = this ; const parameter = 'boost=' + encodeURIComponent ( functions ) ; this . parameters . push ( parameter ) ; return self ; } return { String } api build ( ) { return this . parameters . join ( '&' ) ; } param options param { Boolean } options . on param { String | Array } options . q param { String } options . qparser param { String | Array } options . fl param { Number } options . snippets param { Number } options . fragsize param { Boolean } options . mergeContiguous param { Number } options . maxAnalyzedChars param { Number } options . maxMultiValuedToExamine param { Number } options . maxMultiValuedToMatch param { String } options . alternateField param { Number } options . maxAlternateFieldLength param { String } options . formatter param { String } options . simplePre param { String } options . simplePost param { String } options . fragmenter param { Boolean } options . highlightMultiTerm param { Boolean } options . requireFieldMatch param { Boolean } options . usePhraseHighlighter param { Number } options . regexSlop param { String } options . regexPattern param { Number } options . regexMaxAnalyzedChars param { Boolean } options . preserveMulti param { Boolean } options . payloads return { Query } api hl ( options ) { const self = this ; if ( options . on === false ) { this . parameters . push ( 'hl=false' ) ; } else { this . parameters . push ( 'hl=true' ) ; } if ( options . q !== undefined ) { if ( typeof options . q === 'string' ) { this . parameters . push ( 'hl.q=' + encodeURIComponent ( options . q ) ) ; } else { this . parameters . push ( 'hl.q=' + querystring . stringify ( options . q , '%20AND%20' , ':' ) ) ; } } if ( options . qparser !== undefined ) { this . parameters . push ( 'hl.qparser=' + encodeURIComponent ( options . qparser ) ) ; } if ( options . fl !== undefined ) { if ( typeof options . fl === 'string' ) { this . parameters . push ( 'hl.fl=' + encodeURIComponent ( options . fl ) ) ; } else { this . parameters . push ( 'hl.fl=' + options . fl . join ( ',' ) ) ; } } if ( options . snippets !== undefined ) { this . parameters . push ( 'hl.snippets=' + encodeURIComponent ( options . snippets ) ) ; } if ( options . fragsize !== undefined ) { this . parameters . push ( 'hl.fragsize=' + encodeURIComponent ( options . fragsize ) ) ; } if ( options . mergeContiguous !== undefined ) { this . parameters . push ( 'hl.mergeContiguous=' + encodeURIComponent ( options . mergeContiguous ) ) ; } if ( options . requireFieldMatch !== undefined ) { this . parameters . push ( 'hl.requireFieldMatch=' + encodeURIComponent ( options . requireFieldMatch ) ) ; } if ( options . maxAnalyzedChars !== undefined ) { this . parameters . push ( 'hl.maxAnalyzedChars=' + encodeURIComponent ( options . maxAnalyzedChars ) ) ; } if ( options . maxMultiValuedToExamine !== undefined ) { this . parameters . push ( 'hl.maxMultiValuedToExamine=' + encodeURIComponent ( options . maxMultiValuedToExamine ) ) ; } if ( options . maxMultiValuedToMatch !== undefined ) { this . parameters . push ( 'hl.maxMultiValuedToMatch=' + encodeURIComponent ( options . maxMultiValuedToMatch ) ) ; } if ( options . alternateField ) { this . parameters . push ( 'hl.alternateField=' + encodeURIComponent ( options . alternateField ) ) ; } if ( options . maxAlternateFieldLength !== undefined ) { this . parameters . push ( 'hl.maxAlternateFieldLength=' + encodeURIComponent ( options . maxAlternateFieldLength ) ) ; } if ( options . formatter ) { this . parameters . push ( 'hl.formatter=' + encodeURIComponent ( options . formatter ) ) ; } if ( options . simplePre ) { this . parameters . push ( 'hl.simple.pre=' + encodeURIComponent ( options . simplePre ) ) ; } else { this . parameters . push ( 'hl.simple.pre=<em>' ) ; } if ( options . simplePost ) { this . parameters . push ( 'hl.simple.post=' + encodeURIComponent ( options . simplePost ) ) ; } else { this . parameters . push ( 'hl.simple.post=<%2Fem>' ) ; } if ( options . fragmenter ) { this . parameters . push ( 'hl.fragmenter=' + encodeURIComponent ( options . fragmenter ) ) ; } if ( options . highlightMultiTerm !== undefined ) { this . parameters . push ( 'hl.highlightMultiTerm=' + encodeURIComponent ( options . highlightMultiTerm ) ) ; } if ( options . usePhraseHighlighter !== undefined ) { this . parameters . push ( 'hl.usePhraseHighlighter=' + encodeURIComponent ( options . usePhraseHighlighter ) ) ; } if ( options . regexSlop !== undefined ) { this . parameters . push ( 'hl.regex.slop=' + encodeURIComponent ( options . regexSlop ) ) ; } if ( options . regexPattern ) { this . parameters . push ( 'hl.regex.pattern=' + encodeURIComponent ( options . regexPattern ) ) ; } if ( options . regexMaxAnalyzedChars ) { this . parameters . push ( 'hl.regex.maxAnalyzedChars=' + encodeURIComponent ( options . regexMaxAnalyzedChars ) ) ; } if ( options . preserveMulti !== undefined ) { this . parameters . push ( 'hl.preserveMulti=' + encodeURIComponent ( options . preserveMulti ) ) ; } if ( options . payloads !== undefined ) { this . parameters . push ( 'hl.payloads=' + encodeURIComponent ( options . payloads ) ) ; } return self ; } param options param { Boolean } options . on param { String } options . fl param { String } options . lower param { Boolean } options . lowerIncl param { Number } options . mincount param { Number } options . maxcount param { String } options . prefix param { String } options . regex param { String } options . regexFlag param { Number } options . limit param { String } options . upper param { Boolean } options . upperIncl param { Boolean } options . raw param { String } options . sort return { Query } api terms ( options ) { const self = this ; if ( options . on === false ) { this . parameters . push ( 'terms=false' ) ; } else { this . parameters . push ( 'terms=true' ) ; } if ( options . fl ) { this . parameters . push ( 'terms.fl=' + encodeURIComponent ( options . fl ) ) ; } if ( options . lower !== undefined ) { this . parameters . push ( 'terms.lower=' + encodeURIComponent ( options . lower ) ) ; } if ( options . lowerIncl !== undefined ) { this . parameters . push ( 'terms.lower.incl=' + encodeURIComponent ( options . lowerIncl ) ) ; } if ( options . mincount !== undefined ) { this . parameters . push ( 'terms.mincount=' + options . mincount ) ; } if ( options . maxcount !== undefined ) { this . parameters . push ( 'terms.maxcount=' + options . maxcount ) ; } if ( options . prefix !== undefined ) { this . parameters . push ( 'terms.prefix=' + encodeURIComponent ( options . prefix ) ) ; } if ( options . regex !== undefined ) { this . parameters . push ( 'terms.regex=' + encodeURIComponent ( options . regex ) ) ; } if ( options . regexFlag !== undefined ) { this . parameters . push ( 'terms.regexFlag=' + encodeURIComponent ( options . regexFlag ) ) ; } if ( options . limit !== undefined ) { this . parameters . push ( 'terms.limit=' + options . limit ) ; } if ( options . upper !== undefined ) { this . parameters . push ( 'terms.upper=' + encodeURIComponent ( options . upper ) ) ; } if ( options . upperIncl !== undefined ) { this . parameters . push ( 'terms.upper.incl=' + encodeURIComponent ( options . upperIncl ) ) ; } if ( options . raw !== undefined ) { this . parameters . push ( 'terms.raw=' + encodeURIComponent ( options . raw ) ) ; } if ( options . sort !== undefined ) { this . parameters . push ( 'terms.sort=' + encodeURIComponent ( options . sort ) ) ; } return self ; } }