如何在SolrNet中实现JSON Facet API [英] How to Implement JSON Facet API in SolrNet

查看:84
本文介绍了如何在SolrNet中实现JSON Facet API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to make aggregate functions in Solr I found the way from this Post But I can't implement it in SolrNet

如何在 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);

更新我是用ExtraParams做的

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

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中获取这些值

how to get these values from extraParames

推荐答案

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

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可以只是JSON字符串文字,也可以是序列化为JSON的对象.例如

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

接下来,您需要从Solr的响应中读取构面值.可能有更清洁的方法来执行此操作,但是不涉及更改SolrNet内部结构的一种方法是编写自己的Query方法,该方法也输出原始XML.从原始XML中,您可以读取相应的json.facet节点.

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

这篇关于如何在SolrNet中实现JSON Facet API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆