2017-01-18 37 views
0

在用Elasticsearch制作的搜索引擎中,考虑用户点击结果项目以改善用户印象较多的文档的得分,最佳解决方案是什么?Elasticsearch用户点击反馈

是否有任何工具或插件可以使用或应该从头开始写?

溶液预期考虑以下作为谷歌确实:

  • 的次数每个文档已经显示
  • 次数一个用户点击
  • 查询该用户文档找遍(文档可能在某个特定查询重要的,但在别人不重要)
  • ...
+0

您希望ES了解点击次数?不可能,这是你需要在你的系统中实现的东西,稍后将向ES提交一些点击数据作为提升/埋没值 – Mysterion

+0

我知道我的系统应该将点击数据提交给elasticsearch。我的问题是我如何使弹性搜索考虑这个日志数据作为包含查询和结果点击的评分公式的一部分。它不像提高文档那么简单.. –

+1

是的,这并不简单,但一些简单的特设可以实现,如基于某些公式的查询时间提升let say score = initial_score + clicksw * shows或其他什么 – Mysterion

回答

2

如果您使用rails/ruby​​开发您的API,您可以通过使用搜索解决方案更加智能,每天更多的使用来查看几乎完成这项工作的searchkick

现在,如果你不在轨道上或者你想开发自己的内部实现,这里有几点关于我的架构的建议。

让我们先从基本概述,关键模块,缺点以及适应解决方案中这些缺点的体系结构开始。

则需要

1)计分算法,其中可以定义一个方程,这将产生用于每个文档得分的公式。 让我们考虑你提到的参数

a)每个文档已被显示的次数 b)文件被点击的次数。 c)查询哪个文档被搜索。

现在,因为您尚未提及a)和b)如何适合当前情况。我会假设一个更简单的,但如果你想建立一个真正先进的智能解决方案,我也会结合a)b)和c)。例如 - 文档出现给定关键字的次数。就像我寻找“雪地靴”时,应该考虑这个(出现次数/点击次数),只是当查询或多或少像“雪地靴”不适合所有情况。其中“雪地靴”可以用关键字顺序逼近的下列元素分解为关键字。

{ 
    "keyword": "snow", 
    "document_ids": [3, 5, 6, 8], 
    "document_ids_views": [{ 
     "doc_id": 3, 
     "views ": 110, 
     "clicks": 560 
    }, { 
     "doc_id": 5, 
     "views": 100, 
     "clicks": 78 
    }, { 
     "doc_id": 6, 
     "views": 100, 
     "clicks": 120 
    }, { 
     "doc_id": 3, 
     "views": 100, 
     "clicks": 465 
    }] 
} 

{ 
    "keyword": "boots", 
    "document_ids": [3, 5, 6, 8], 
    "document_ids_views": [{ 
     "doc_id": 3, 
     "views ": 100, 
     "clicks": 56 
    }, { 
     "doc_id": 5, 
     "views": 100, 
     "clicks": 78 
    }, { 
     "doc_id": 6, 
     "views": 100, 
     "clicks": 120 
    }, { 
     "doc_id": 3, 
     "views": 100, 
     "clicks": 465 
    }] 
} 

以上是存储在单独数据库中的每个关键字的汇总数据。

像这样,我会建立一个统计数据的元数据在一个单独的数据存储让我们说mongo。如果我已经有“雪”在我的元和新的查询与这个关键字我会更新相同的元文档。

现在我想讨论一下不足,以及为什么我选择将它们保存在单独的数据库中,而不是将它们追加到elasticsearch文档中。

我不想每次弹出一个新的查询来更新弹性文档中的点击次数和浏览次数时,通过elasticsearch集群来锤击,因为我知道更新非常I/O,并且有倒排索引合并。

现在为了弥补这个缺点,我会每天或每日批量作业将这些元信息以弹性方式移植到每个文档中。我会用这个新的元信息重建整个集群,并将别名从旧索引移动到新索引,而不会有任何停机时间。

现在要将此信息关联或添加到弹性文档中,我将使用parent-child documents relationship来映射具有与此关联的关键字的弹性文档。

所以我的基本父文件和子文件可以像

父文档

PUT /index/type/3 
{ 
    "name": "Reebok shoes", 
    "category": "snow boots", 
    "price": 120 
} 

子文档

PUT /index/type_meta/1?parent=3 


    { 
    "keyword": "boots", 
    "document_id": 3, 
    "doc_id": 3, 
    "views ": 100, 
    "clicks": 56 
} 

PUT /index/type_meta/1?parent=3 


{ 
    "keyword": "snow", 
    "document_id": 3, 
    "doc_id": 3, 
    "views ": 110, 
    "clicks": 560 
} 

以上亲子文件几乎解释我在如何建立每个文档的搜索统计数据元。

到现在为止,我们已经构建了一个非常聪明的解决方案来收集搜索统计数据的事件数据,并成功地将它们与每个文档进行弹性关联。

让我们开始寻找得分查询这里 -

我不会深入在这里设计了得分算法中,但我会去更倾向于执行那些能得分根据意见文件的查询,点击相关与关键字和关键字的相关性。

Function score query

Script score

现在,我可能会选择给予更多的权重,以在名称匹配比的类别。这就是从你的用例角度来看,我不会为你设计分数公式。

{ 
    "query": { 
     "function_score": { 
      "query": { 
       "match_all": {} 
      }, 
      "boost": "5", 
      "functions": [{ 
       "filter": { 
        "match": { 
         "name": "snow" 
        } 
       }, 
       "random_score": {}, 
       "weight": 200 
      }, { 
       "filter": { 
        "match": { 
         "name": "boots" 
        } 
       }, 
       "weight": 200 
      }, { 
       "filter": { 
        "match": { 
         "category": "snow" 
        } 
       }, 
       "random_score": {}, 
       "weight": 100 
      }, { 
       "filter": { 
        "match": { 
         "category": "boots" 
        } 
       }, 
       "weight": 100 
      }, { 
       "filter": { 
        "query": { 
         "has_parent": { 
          "type": "type_meta", 
          "query": { 
           "match": { 
            "keyword": "snow" 
           } 
          } 
         } 
        } 
       }, 
       "script_score": { 
        "script": { 
         "lang": "painless", 
         "inline": "_score + 20*doc['clicks'].value + 40 * doc['views].value" 
        } 
       } 
      }, { 
       "filter": { 
        "query": { 
         "has_parent": { 
          "type": "type_meta", 
          "query": { 
           "match": { 
            "keyword": "boots" 
           } 
          } 
         } 
        } 
       }, 
       "script_score": { 
        "script": { 
         "lang": "painless", 
         "inline": "_score + 20*doc['clicks'].value + 40 * doc['views].value" 
        } 
       } 
      }], 

      "score_mode": "max", 
      "boost_mode": "multiply" 
     } 
    } 
} 

所以,你可以使用呈三角像上面的查询,我刚才已经选择了与演示升压PARAMS一个非常简单的公式,每个子句,该查询可以furthur的实现提前得分算法中进行重构。

脚本分数功能在这里很重要,因为我首先根据单个父文档的搜索关键字筛选子文档,然后使用脚本分数来使用点击和查看计数来影响我的总体文档分数。

现在,这是一种我期待在我的项目中实现的解决方案,我愿意为我的解决方案提供建议和改进。

请分享您的建议和改进。

希望这会有所帮助 谢谢

+0

感谢您的分享。 –