简体   繁体   English

如何在SolrNet中实现JSON Facet API

[英]How to Implement JSON Facet API in SolrNet

I want to make aggregate functions in Solr I found the way from this Post But I can't implement it in SolrNet 我想在Solr中创建聚合函数,我从这篇文章中找到了方法,但是我无法在SolrNet中实现它

How to Implement JSON Facet API in 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);

Update I did it using ExtraParams 更新我使用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;
    }
}

how to get these values from extraParames 如何从extraParames获取这些值

To the best of my knowledge SolrNet does not yet have a .NET API supporting json.facet. 据我所知,SolrNet还没有支持json.facet的.NET API。 However, you can always append extra query parameters via the QueryOptions.ExtraParams property. 但是,您始终可以通过QueryOptions.ExtraParams属性附加其他查询参数。 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. YOUR_JSON_FACET可以只是JSON字符串文字,也可以是序列化为JSON的对象。 eg 例如

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. 接下来,您需要从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. 可能有更清洁的方法来执行此操作,但是不涉及更改SolrNet内部结构的一种方法是编写自己的Query方法,该方法也输出原始XML。 From that raw XML, you can just read the appropriate json.facet nodes. 从原始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)
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM