【问题标题】:Workaround to group solr search result by collection field按集合字段对 solr 搜索结果进行分组的解决方法
【发布时间】:2019-10-11 22:12:17
【问题描述】:

我是 Solr 的初学者。可能有错误。对不起。 我正在使用版本 7.7.1。 假设有下一个文件:

{
  "documents": [
    {
      "id": 1,
      "category": [
        "a",
        "b"
      ],
      "score":0.10 //lucene score
    },
    {
      "id": 2,
      "category": [
        "b",
        "c",
        "d",
        "e"
      ],
      "score":0.20 //lucene score
    },
    {
      "id": 3,
      "category": [
        "a",
        "e"
      ],
      "score":0.30 //lucene score
    },
    {
      "id": 4,
      "category": [
        "d",
        "e"
      ],
      "score":0.40 //lucene score
    },
    {
      "id": 5,
      "category": [
        "a",
        "c"
      ],
      "score":0.50 //lucene score
    }
  ]
}

主要任务是下一个。我得到 3 个或更多不同的类别,我只需要一个文档,每个类别的得分最高。换句话说,我需要按类别字段对结果进行分组,每个组都必须按分数 desc 排序,并且每个组都必须限制为 1。

例如得到 a,b,c 类别的结果必须包含 3 个文档

document with id == 5 for a category
document with id == 2 for b category
document with id == 5 for c category

是否可以通过单个请求创建 solr 查询来获得这样的结果?

我尝试了接下来的方法,但它们没有帮助或效果不佳:

  1. 由于类别字段是集合,因此不考虑分组。

  2. Faceting 仅返回结果数。我需要一份完整的文件。

  3. 可以对每个类别进行请求。但是一次可以有50个类别,我想在solr中发出50个请求会很耗时。

感谢和问候

【问题讨论】:

    标签: search solr lucene


    【解决方案1】:

    json.facet 在这里会有所帮助。您可以使用以下查询,它会根据您的需要为您提供响应。此查询将首先为按升序排序的类别字段创建存储桶,然后使用通过“qq”参数传递的查询的 lucene 分数排序的嵌套 id 存储桶。

    我使用了一个函数查询,我们用它来评估给定查询的 lucene 分数。目前,这是一个简单的查询,但您也可以创建一个复杂的并传入 qq 参数。阅读此处:- https://lucene.apache.org/solr/guide/6_6/function-queries.html 获取更多关于函数查询的信息。

    q=*&qq=category:a&json.facet={
    categories:{
        type:terms,
        field:category,
        sort:{index:asc},
        facet:{
            id:{
                type:terms,
                field:id,
                sort:"query_score desc",
                facet:{
                    query_score:"min(if(exists(query($qq)),query($qq),0))"
                }
            }
        }
    }
    

    }

    [上述查询的响应]

    {
      "responseHeader":{
        "status":0,
        "QTime":7,
        "params":{
          "qq":"category:a",
          "q":"*",
          "json.facet":"{ categories:{ type:terms, field:category, sort:{index:asc}, facet:{ id:{ type:terms, field:id, sort:\"query_score desc\", facet:{ query_score:\"min(if(exists(query($qq)),query($qq),0))\" } } } } }",
          "indent":"on",
          "fl":"*,query($qq,-1)",
          "rows":"0",
          "wt":"json"}},
      "response":{"numFound":5,"start":0,"docs":[]
      },
      "facets":{
        "count":5,
        "categories":{
          "buckets":[{
              "val":"a",
              "count":3,
              "id":{
                "buckets":[{
                    "val":"1",
                    "count":1,
                    "query_score":0.5389965176582336},
                  {
                    "val":"3",
                    "count":1,
                    "query_score":0.5389965176582336},
                  {
                    "val":"5",
                    "count":1,
                    "query_score":0.5389965176582336}]}},
            {
              "val":"b",
              "count":2,
              "id":{
                "buckets":[{
                    "val":"1",
                    "count":1,
                    "query_score":0.5389965176582336},
                  {
                    "val":"2",
                    "count":1,
                    "query_score":0.0}]}},
            {
              "val":"c",
              "count":2,
              "id":{
                "buckets":[{
                    "val":"5",
                    "count":1,
                    "query_score":0.5389965176582336},
                  {
                    "val":"2",
                    "count":1,
                    "query_score":0.0}]}},
            {
              "val":"d",
              "count":2,
              "id":{
                "buckets":[{
                    "val":"2",
                    "count":1,
                    "query_score":0.0},
                  {
                    "val":"4",
                    "count":1,
                    "query_score":0.0}]}},
            {
              "val":"e",
              "count":3,
              "id":{
                "buckets":[{
                    "val":"3",
                    "count":1,
                    "query_score":0.5389965176582336},
                  {
                    "val":"2",
                    "count":1,
                    "query_score":0.0},
                  {
                    "val":"4",
                    "count":1,
                    "query_score":0.0}]}}]}}}
    

    有关 json.facet 的更多信息:- https://lucene.apache.org/solr/guide/7_2/json-facet-api.html

    【讨论】:

    • 感谢您的回答。看起来它从结果中获取所有可能的类别并为每个类别创建一个桶。我的意思略有不同,因为需要对类别进行额外的检查,但总比提出很多请求要好。再次感谢。
    • 您的示例中还有另一个问题。是否可以按文档的“分数”对嵌套分面进行排序?我已阅读您在邮件中提供的文档。看起来不可能使用文档的“分数”来对存储桶进行排序。不幸的是,这是我需要执行 Solr 请求而不是请求数据库的主要原因。你能告诉我是否可以修复吗?谢谢
    • 当您说“分数”时,您是在谈论 lucene 分数还是您为每个文档创建的自定义字段?而且,在 json 方面,我已经在使用您的自定义字段“score”进行排序。
    • 当我说分数时,我的意思是 lucene 分数(不是自定义的)。很抱歉,如果它混淆了。
    • 在我的示例中我的意思也是 lucene 分数。我的生产 solr 中没有自定义“分数”。当我在 ... score:"min(score)..." 中插入分数时,我有消息'undefined field: \"score\"'的异常
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-23
    • 1970-01-01
    • 2016-01-09
    相关资源
    最近更新 更多