【问题标题】:ElasticSearch Order By String LengthElasticSearch 按字符串长度排序
【发布时间】:2015-06-29 05:15:03
【问题描述】:

我正在通过 NEST c# 使用 ElasticSearch。我有大量有关人员的信息

{
   firstName: 'Frank',
   lastName: 'Jones',
   City: 'New York'
}

我希望能够按姓氏过滤和排序此项目列表以及按长度排序,这样名字中只有 5 个字符的人将位于结果集的开头,然后是 10 个字符的人字符。

所以我想做一些伪代码 list.wildcard("j*").sort(m => lastName.length)

【问题讨论】:

    标签: elasticsearch nest sense


    【解决方案1】:

    您可以使用script-based sorting 进行排序。

    作为一个玩具示例,我用一些文档设置了一个简单的索引:

    PUT /test_index
    
    POST /test_index/doc/_bulk
    {"index":{"_id":1}}
    {"name":"Bob"}
    {"index":{"_id":2}}
    {"name":"Jeff"}
    {"index":{"_id":3}}
    {"name":"Darlene"}
    {"index":{"_id":4}}
    {"name":"Jose"}
    

    然后我可以这样排序搜索结果:

    POST /test_index/_search
    {
       "query": {
          "match_all": {}
       },
       "sort": {
          "_script": {
             "script": "doc['name'].value.length()",
             "type": "number",
             "order": "asc"
          }
       }
    }
    ...
    {
       "took": 2,
       "timed_out": false,
       "_shards": {
          "total": 5,
          "successful": 5,
          "failed": 0
       },
       "hits": {
          "total": 4,
          "max_score": null,
          "hits": [
             {
                "_index": "test_index",
                "_type": "doc",
                "_id": "1",
                "_score": null,
                "_source": {
                   "name": "Bob"
                },
                "sort": [
                   3
                ]
             },
             {
                "_index": "test_index",
                "_type": "doc",
                "_id": "4",
                "_score": null,
                "_source": {
                   "name": "Jose"
                },
                "sort": [
                   4
                ]
             },
             {
                "_index": "test_index",
                "_type": "doc",
                "_id": "2",
                "_score": null,
                "_source": {
                   "name": "Jeff"
                },
                "sort": [
                   4
                ]
             },
             {
                "_index": "test_index",
                "_type": "doc",
                "_id": "3",
                "_score": null,
                "_source": {
                   "name": "Darlene"
                },
                "sort": [
                   7
                ]
             }
          ]
       }
    }
    

    要按长度过滤,我可以以类似的方式使用script filter:

    POST /test_index/_search
    {
       "query": {
          "filtered": {
             "query": {
                "match_all": {}
             },
             "filter": {
                "script": {
                   "script": "doc['name'].value.length() > 3",
                   "params": {}
                }
             }
          }
       },
       "sort": {
          "_script": {
             "script": "doc['name'].value.length()",
             "type": "number",
             "order": "asc"
          }
       }
    }
    ...
    {
       "took": 3,
       "timed_out": false,
       "_shards": {
          "total": 5,
          "successful": 5,
          "failed": 0
       },
       "hits": {
          "total": 3,
          "max_score": null,
          "hits": [
             {
                "_index": "test_index",
                "_type": "doc",
                "_id": "4",
                "_score": null,
                "_source": {
                   "name": "Jose"
                },
                "sort": [
                   4
                ]
             },
             {
                "_index": "test_index",
                "_type": "doc",
                "_id": "2",
                "_score": null,
                "_source": {
                   "name": "Jeff"
                },
                "sort": [
                   4
                ]
             },
             {
                "_index": "test_index",
                "_type": "doc",
                "_id": "3",
                "_score": null,
                "_source": {
                   "name": "Darlene"
                },
                "sort": [
                   7
                ]
             }
          ]
       }
    }
    

    这是我使用的代码:

    http://sense.qbox.io/gist/22fef6dc5453eaaae3be5fb7609663cc77c43dab

    P.S.:如果任何姓氏包含空格,您可能需要在该字段上使用"index": "not_analyzed"。

    【讨论】:

    • 假设他经常在很多文档上执行此搜索,是否值得只索引长度?
    • 感谢您的反馈。 @Robin:在大多数情况下,我的数据不会改变,所以索引长度我觉得会是有益的。如果您有任何参考资料,您可以指出我会很棒。
    • 太快按回车键。我在使用 Sense 时也遇到了一个问题,它会抛出异常,指出 groovy 已禁用。将 groovy 指定为语言并更改删除 _script 上的下划线,然后将我引向更多错误的路径。我知道这很简单,对运行您的示例的环境有什么建议吗?我尝试了你发送到 qBox 的链接,但它把我带到了一个空的编辑器,也许你忘了保存代码?
    • 我在 ES 1.3.4 上运行了这个。对于 1.4+,您必须启用 CORS 才能使用 Sense 应用程序以及动态脚本。不过,索引长度可能是更好的生产解决方案。我认为,您必须计算代码中的长度。不过,不确定为什么编辑器对您来说是空的;这个对我有用。你使用的是什么浏览器?您在控制台中看到任何 JavaScript 错误吗?你能帮我把它们贴在某个地方吗?
    • 谢谢 Sloan,可能是我安装的防火墙,今晚晚些时候再试一次
    猜你喜欢
    • 1970-01-01
    • 2015-07-29
    • 1970-01-01
    • 2015-03-15
    • 1970-01-01
    • 1970-01-01
    • 2014-05-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多