diff --git a/rest/src/main/groovy/whelk/rest/api/SearchUtils.groovy b/rest/src/main/groovy/whelk/rest/api/SearchUtils.groovy index a6a9395b2a..9118b604a7 100644 --- a/rest/src/main/groovy/whelk/rest/api/SearchUtils.groovy +++ b/rest/src/main/groovy/whelk/rest/api/SearchUtils.groovy @@ -383,6 +383,7 @@ class SearchUtils { aggregation['buckets'].each { bucket -> String itemId = bucket['key'] + Map observation if (key in multiSelected.keySet()) { String param = makeParam(key, itemId) boolean isSelected = escapeQueryParam(itemId) in multiSelected[key] @@ -390,22 +391,28 @@ class SearchUtils { ? baseUrlForKey.replace("&${param}", '') // FIXME: generate up-link in a cleaner way : "${baseUrlForKey}&${param}" - Map observation = ['totalItems': bucket.getAt('doc_count'), + observation = ['totalItems': bucket.getAt('doc_count'), 'view': [(JsonLd.ID_KEY): searchPageUrl], '_selected': isSelected, 'object': lookup.chip(itemId)] - - observations << observation } else { String searchPageUrl = "${baseUrlForKey}&${ESQuery.AND_PREFIX}${makeParam(key, itemId)}" - Map observation = ['totalItems': bucket.getAt('doc_count'), + observation = ['totalItems': bucket.getAt('doc_count'), 'view': [(JsonLd.ID_KEY): searchPageUrl], 'object': lookup.chip(itemId)] - observations << observation } + + Map bucketAggs = bucket[ESQuery.FILTERED_AGG_NAME] + if (bucketAggs) { + Map nestedAggs = bucketAggs.clone() + nestedAggs.remove('doc_count') + observation = addSlices(lookup, observation, nestedAggs, baseUrlForKey, null, multiSelected) + } + + observations << observation } if (observations) { diff --git a/whelk-core/src/main/groovy/whelk/search/ESQuery.groovy b/whelk-core/src/main/groovy/whelk/search/ESQuery.groovy index 43dcefe7cf..9bf163ca0f 100644 --- a/whelk-core/src/main/groovy/whelk/search/ESQuery.groovy +++ b/whelk-core/src/main/groovy/whelk/search/ESQuery.groovy @@ -948,16 +948,20 @@ class ESQuery { } keys.each { key -> - String sort = tree[key]?.sort =='key' ? '_key' : '_count' - def sortOrder = tree[key]?.sortOrder =='asc' ? 'asc' : 'desc' + Map treeNode = tree[key] + String sort = treeNode?.sort =='key' ? '_key' : '_count' + def sortOrder = treeNode?.sortOrder =='asc' ? 'asc' : 'desc' String termPath = getInferredTermPath(key) // Core agg query - query[termPath] = ['terms': [ + def coreQuery = [ + 'terms': [ 'field': termPath, - 'size' : tree[key]?.size ?: size, - 'order': [(sort): sortOrder]] + 'size' : treeNode?.size ?: size, + 'order': [(sort): sortOrder] + ] ] + query[termPath] = coreQuery // If field is nested, wrap agg query with nested nestedFields.find{ key.startsWith(it) }?.with { nestedField -> @@ -974,8 +978,23 @@ class ESQuery { 'filter': ['bool': ['must': filters]] ] - if (tree[key].subItems instanceof Map) { - query[termPath]['aggs'] = buildAggQuery(tree[key].subItems, multiSelectFilters, size) + if (treeNode.subItems instanceof Map) { + def subAggQuery = buildAggQuery(treeNode.subItems, multiSelectFilters, size) + // TODO: factor out parts of buildAggQuery to avoid this reshuffle. + //coreQuery['aggs'] = subAggQuery + // TODO: handle multiple keys. + def iter = subAggQuery.iterator() + if (iter.hasNext()) { + def entry = iter.next() + def subkey = entry.getKey() + def subvalue = entry.getValue() + coreQuery['aggs'] = [ + (FILTERED_AGG_NAME): [ + 'aggs': [ (subkey): subvalue['aggs'][FILTERED_AGG_NAME] ], + 'filter': subvalue['filter'] + ] + ] + } } } return query