问题
I want to make aggregate functions in Solr I found the way from this Post But I can't implement it in SolrNet
How to Implement JSON Facet API in SolrNet
ISolrOperations<DeviceReadings> solr = connection.GetSolrInstance();
QueryOptions queryOption = new QueryOptions
{
Rows = 0,
FilterQueries = new ISolrQuery[] {
new SolrQueryByField("playerId", query.PlayerId.ToString()),
new SolrQueryByRange<DateTime>("dateTime", query.DateTimeFrom, query.DateTimeTo)
},
Facet = new FacetParameters
{
Queries = new List<ISolrFacetQuery>
{
new SolrFacetFieldQuery("heartRate")
}
}
};
queryOption.ExtraParams = new KeyValuePair<string, string>[] {
new KeyValuePair<string,string>("wt", "xml")
};
//Execute the query
solrResults = solr.Query(SolrQuery.All, queryOption);
Update I did it using ExtraParams
queryOption.ExtraParams = new KeyValuePair<string, string>[] {
new KeyValuePair<string,string>("wt", "xml"),
new KeyValuePair<string,string>("json.facet", "{heartRateMin: 'min(heartRate)',heartRateMax: 'max(heartRate)',heartRateAvg: 'avg(heartRate)',distance: 'sum(distance)',calories: 'sum(calories)'}")
};
solrResults = await solr.QueryAsync(SolrQuery.All, queryOption);
ReadingsResponseExtraction extractResponse = new ReadingsResponseExtraction();
extractResponse.SetHeader(queryResponce, solrResults);
extractResponse.SetBody(queryResponce, solrResults);
extractResponse.SetFacets(queryResponce, solrResults);
//Return response;
return queryResponce;
ReadingsResponseExtraction.cs
internal class ReadingsResponseExtraction
{
//Extract parts of the SolrNet response and set them in QueryResponse class
internal void SetHeader(DeviceQueryResponse queryResponce, SolrQueryResults<DeviceReadings> solrResults)
{
queryResponce.QueryTime = solrResults.Header.QTime;
queryResponce.Status = solrResults.Header.Status;
queryResponce.TotalHits = solrResults.NumFound;
}
internal void SetBody(DeviceQueryResponse queryResponce, SolrQueryResults<DeviceReadings> solrResults)
{
queryResponce.Result = (List<DeviceReadings>)solrResults;
}
internal void SetFacets(DeviceQueryResponse queryResponse, SolrQueryResults<DeviceReadings> solrResults)
{
queryResponse.HeartRateMin = (int)solrResults.Stats["heartRate"].Min;
queryResponse.HeartRateMax = (int)solrResults.Stats["heartRate"].Max;
queryResponse.HeartRateAvg = (int)solrResults.Stats["heartRate"].Mean;
queryResponse.Distance = solrResults.Stats["distance"].Sum;
queryResponse.Calories = solrResults.Stats["calories"].Sum;
}
}
how to get these values from extraParames
回答1:
To the best of my knowledge SolrNet does not yet have a .NET API supporting json.facet. However, you can always append extra query parameters via the QueryOptions.ExtraParams property. Based on your example:
queryOption.ExtraParams = new KeyValuePair<string, string>[] {
new KeyValuePair<string,string>("wt", "xml"),
new KeyValuePair<string,string("json.facet", "YOUR_JSON_FACET"),
};
YOUR_JSON_FACET can either just be a JSON string literal, or an object that is serialized into JSON. e.g.
var jsonFacet = new
{
heartRate = new {
type= "terms",
field= "heartRate",
}
};
JsonConvert.SerializeObject(jsonFacet, Formatting.None);
Next, you need to read the facet values out of the response from Solr. There are likely cleaner ways to do this, but one way that doesn't involve altering SolrNet internals is to write your own Query method that also outputs the raw XML. From that raw XML, you can just read the appropriate json.facet nodes.
public static SolrQueryResults<T> QueryWithRawXml<T>(this ISolrOperations<T> operations,
ISolrQuery query, QueryOptions queryOptions, out XDocument xml)
{
var executor = (SolrQueryExecuter<T>)ServiceLocator.Current.GetInstance<ISolrQueryExecuter<T>>();
var connectionKey = string.Format("{0}.{1}.{2}", typeof(SolrConnection), typeof(T), typeof(SolrConnection));
var connection = ServiceLocator.Current.GetInstance<ISolrConnection>(connectionKey);
var parser = ServiceLocator.Current.GetInstance<ISolrAbstractResponseParser<T>>();
var parameters = executor.GetAllParameters(query, queryOptions);
var responseXml = connection.Get(executor.Handler, parameters);
xml = XDocument.Parse(responseXml);
var results = new SolrQueryResults<T>();
parser.Parse(xml, results);
return results;
}
public IEnumerable<KeyValuePair<string, int> GetJsonFacets(
XDocument xml, string facetFieldName, string countFieldName = "count")
{
var response = xml.Element("response");
if (response == null)
{
yield break;
}
var mainFacetNode = response
.Elements("lst")
.FirstOrDefault(e => e.Attribute("name")?.Value == "facets");
if (mainFacetNode == null)
{
yield break;
}
var groupFacetElement = mainFacetNode
.Elements("lst")
.FirstOrDefault(x => x.Attribute("name")?.Value == facetFieldName);
if (groupFacetElement == null)
{
yield break;
}
var buckets = groupFacetElement.Elements("arr")
.FirstOrDefault(x => x.Attribute("name")?.Value == "buckets");
if (buckets == null)
{
yield break;
}
foreach (var bucket in buckets.Elements("lst"))
{
var valNode = bucket.Elements()
.FirstOrDefault(x => x.Attribute("name")?.Value == "val");
var countNode = bucket.Elements()
.FirstOrDefault(x => x.Attribute("name")?.Value == countFieldName);
int count;
if (valNode != null && countNode != null &&
int.TryParse(countNode.Value, out count))
{
yield return new KeyValuePair<string, int>(valNode.Value,count)
}
}
}
来源:https://stackoverflow.com/questions/49965683/how-to-implement-json-facet-api-in-solrnet