如何查询我的玩家并返回他们的分数顺序?

时间:2017-02-16 05:50:56

标签: elasticsearch

我有以下内容:

PUT players
{
  "mappings": {
    "player": {
      "properties": {
        "name": {
          "type": "string"
        }
      }
    }
  }
}

PUT players/player/1
{
  "name": "Dave"
}
PUT players/player/2
{
  "name": "Dan"
}
PUT players/player/3
{
  "name": "Macey"
}



PUT score
{
  "mappings": {
    "score": {
      "properties": {
        "player": {
          "type": "string"
        },
        "score": {
          "type": "integer"
        }
      }
    }
  }
}
PUT score/score/1
{
  "player": "3",
  "action": "10"
}
PUT score/score/2
{
  "player": "2",
  "action": "5"
}
PUT score/score/3
{
  "player": "3",
  "action": "10"
}
PUT score/score/4
{
  "player": "2",
  "action": "7"
}
PUT score/score/5
{
  "player": "1",
  "action": "1"
}
PUT score/score/6
{
  "player": "1",
  "action": "2"
}
PUT score/score/7
{
  "player": "1",
  "action": "2"
}
PUT score/score/8
{
  "player": "1",
  "action": "1"
}
PUT score/score/9
{
  "player": "1",
  "action": "8"
}

我不知道我在做什么。我需要按总分(按降序排列)对球员进行排序。所以,如果我查询“Da”,我想得到:

1. Dave - 14
2. Dan - 12

到目前为止,我有:

GET /players/_search
{
  "query": {
    "bool": {
      "must": {
        "term": {
          "name": "Da"
        }
      }
    }
  }
}

我知道这不对。我主要来自一个SQL世界,我很难搞清楚如何加入表并按字段计数。感谢您的任何提示!

2 个答案:

答案 0 :(得分:0)

为了解释handling relationships上的文档,Elasticsearch文档是孤立的,没有办法在文档之间建立简单的关系。

要解决这个困境,最简单的解决方案之一就是将您的数据非正规化 1 ,在您的{{1}中存储您的玩家数据(可能会修剪到您的搜索工作所需的数据)文档并处理该索引。

例如,您可以将score索引定义为

score

你会用

填写它
{
    "mappings": {
        "score": {
            "properties": {
                "player": {
                    "properties": {
                        "id": {
                            "type": "integer"
                        },
                        "nom": {
                            "type": "string",
                            "index": "not_analyzed"
                        }
                    }
                },
                "score": {
                    "type": "integer"
                }
            }
        }
    }
}

请注意,我已将PUT score/score/1 { "player": { "id": 3, "name": "Macey" }, "score": "10" } PUT score/score/2 { "player": { "id": 2, "name": "Dan" }, "score": "5" } PUT score/score/3 { "player": { "id": 3, "name": "Macey" }, "score": "10" } 键替换为action

假设您需要对名称进行前缀查询(scoreplayer.name的原因),您的查询将如下所示

not_analyzed

最后,要获得每位玩家的最高分,您可以使用聚合:

"query": {
    "bool": {
        "must": {
            "prefix": {
                "player.name": "da"
            }
        }
    }
}

顶级agg按玩家ID定义存储桶,按{ "query": { "bool": { "must": { "prefix": { "player.name": "da" } } } }, "aggs" : { "players" : { "terms" : { "field" : "player.id" , "order" : { "maxvalue" : "desc" } }, "aggs" : { "maxvalue": { "max" : { "field" : "score" } }, "maxscore": { "top_hits": { "sort": [ { "score": { "order": "desc" } } ], "size" : 1 } } } } } } 子聚合对其进行排序,然后通过maxvalue聚合提取最高得分。

结果在Elasticsearch中有点冗长,你会得到类似的东西(减去查询结果)

top_hits

1 我知道它在SQL世界中是个坏词,但你已经习惯了。

答案 1 :(得分:0)

您可以利用子父关系来支持您的数据。您可以将玩家个人资料创建为父文档,将他们的分数创建为子文档。以下是parent-child relationship document的链接。

我为你创建了支持父子关系的映射

    PUT testindex12
    {
        "settings": {
            "analysis": {}
        },
        "mappings": {
            "player": {
                "properties": {
                    "players": {
                        "type": "string"
                    }
                }
            },
            "score": {
                "_parent": {
                    "type": "player"
                },
                "_routing": {
                    "required": true
                },
                "properties": {
                    "player": {
                        "type": "string"
                    },
                    "score": {
                        "type": "integer"
                    }
                }
            }
        }
    }

有关映射父子检查this link的更多信息。

索引父文件和子文件。

POST testindex12/player/1
{
  "player" : "sachin"
}

POST testindex12/player/2
{
  "player" : "rahul"
}

POST testindex12/player/3
{
  "player" : "virat"
}


POST testindex12/score?parent=3
{
  "score": 789
}

有关索引父子文档的更多信息,请参阅this link

以下是我只是在名称上进行过滤的查询,在这里我想指向你,因为你试图对玩家的名字进行部分搜索,所以你可以在名字上使用前缀搜索。以下是prefix query的文档。为了根据分数对文档进行评分,我使用了功能评分。您可以找到有关他们的更多信息here

POST testindex12/_search
{
    "query": {
        "bool": {

            "must": [
              { "prefix": {
                "player": {
                  "value": "sa"
                }
              }
                },{
                "has_child": {
                    "type": "score",
                    "score_mode": "sum",
                    "query": {
                        "function_score": {
                            "query": {
                                "match_all": {}
                            },
                            "score_mode": "sum",
                            "boost_mode": "sum",
                            "script_score": {
                                "script": "_score + doc['score'].value"
                            }
                        }
                    }
                }
            }]
        }
    }
}

我将不再使用nikoshr做的其他解决方案,因为聚合总共有不同的用途,当然也不能用于评分文档。

希望这会有所帮助。 感谢