/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.search.grouping.distributed.requestfactory;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.grouping.GroupDocs;
import org.apache.lucene.search.grouping.TopGroups;
import org.apache.lucene.util.BytesRef;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.GroupParams;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.ShardParams;
import org.apache.solr.common.util.StrUtils;
import org.apache.solr.handler.component.ResponseBuilder;
import org.apache.solr.handler.component.ShardDoc;
import org.apache.solr.handler.component.ShardRequest;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.search.grouping.distributed.ShardRequestFactory;
import org.apache.solr.search.grouping.distributed.command.QueryCommandResult;
import java.util.*;
/**
*
*/
public class StoredFieldsShardRequestFactory implements ShardRequestFactory {
@Override
public ShardRequest[] constructRequest(ResponseBuilder rb) {
HashMap<String, Set<ShardDoc>> shardMap = new HashMap<>();
for (TopGroups<BytesRef> topGroups : rb.mergedTopGroups.values()) {
for (GroupDocs<BytesRef> group : topGroups.groups) {
mapShardToDocs(shardMap, group.scoreDocs);
}
}
for (QueryCommandResult queryCommandResult : rb.mergedQueryCommandResults.values()) {
mapShardToDocs(shardMap, queryCommandResult.getTopDocs().scoreDocs);
}
ShardRequest[] shardRequests = new ShardRequest[shardMap.size()];
SchemaField uniqueField = rb.req.getSchema().getUniqueKeyField();
int i = 0;
for (Collection<ShardDoc> shardDocs : shardMap.values()) {
ShardRequest sreq = new ShardRequest();
sreq.purpose = ShardRequest.PURPOSE_GET_FIELDS;
sreq.shards = new String[] {shardDocs.iterator().next().shard};
sreq.params = new ModifiableSolrParams();
sreq.params.add( rb.req.getParams());
sreq.params.remove(GroupParams.GROUP);
sreq.params.remove(CommonParams.SORT);
sreq.params.remove(ResponseBuilder.FIELD_SORT_VALUES);
String fl = sreq.params.get(CommonParams.FL);
if (fl != null) {
fl = fl.trim();
// currently, "score" is synonymous with "*,score" so
// don't add "id" if the fl is empty or "score" or it would change the meaning.
if (fl.length()!=0 && !"score".equals(fl) && !"*".equals(fl)) {
sreq.params.set(CommonParams.FL, fl+','+uniqueField.getName());
}
}
List<String> ids = new ArrayList<>(shardDocs.size());
for (ShardDoc shardDoc : shardDocs) {
ids.add(shardDoc.id.toString());
}
sreq.params.add(ShardParams.IDS, StrUtils.join(ids, ','));
shardRequests[i++] = sreq;
}
return shardRequests;
}
private void mapShardToDocs(HashMap<String, Set<ShardDoc>> shardMap, ScoreDoc[] scoreDocs) {
for (ScoreDoc scoreDoc : scoreDocs) {
ShardDoc solrDoc = (ShardDoc) scoreDoc;
Set<ShardDoc> shardDocs = shardMap.get(solrDoc.shard);
if (shardDocs == null) {
shardMap.put(solrDoc.shard, shardDocs = new HashSet<>());
}
shardDocs.add(solrDoc);
}
}
}