如何在SolrNet中实现JSON Facet API

时间:2018-04-22 12:01:46

标签: c# asp.net solr solrnet

我想在Solr中创建聚合函数我从Post找到了方法 但我无法在SolrNet中实现它

如何在 SolrNet

中实施 JSON Facet API
        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);

更新 我是用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;
    }
}

如何从extraParames

获取这些值

1 个答案:

答案 0 :(得分:2)

据我所知,SolrNet还没有支持json.facet的.NET API。但是,您始终可以通过QueryOptions.ExtraParams属性追加额外的查询参数。根据您的示例:

queryOption.ExtraParams = new KeyValuePair<string, string>[] {
    new KeyValuePair<string,string>("wt", "xml"),
    new KeyValuePair<string,string("json.facet", "YOUR_JSON_FACET"),
};

YOUR_JSON_FACET既可以是JSON字符串文字,也可以是序列化为JSON的对象。例如

var jsonFacet = new
{
    heartRate = new {
        type= "terms",
        field= "heartRate",
    }
};

JsonConvert.SerializeObject(jsonFacet, Formatting.None);

接下来,您需要从Solr的响应中读取构面值。可能有更简洁的方法来做到这一点,但是一种不涉及改变SolrNet内部的方法是编写自己的Query方法,该方法也输出原始XML。从原始XML中,您可以只读取相应的json.facet节点。

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)
        }
    }
}