# 比赛列表

**URL:** https://heroiclabs.com/docs/zh/nakama/concepts/multiplayer/match-listing/
**Summary:** 比赛标签可用于根据精确匹配或查询，筛选活动的多人游戏比赛，以查找和排序最合适的比赛。列出比赛有助于在创建新比赛之前展示玩家大厅和搜索现有比赛。

---


# 比赛列表

[匹配程序](../matchmaker/)可供玩家查找对手（或队友），以便在新比赛中与其一起玩游戏，而比赛列表可用于显示玩家当前可以立即加入的活动比赛。

您可以使用比赛列表方便地返回任意给定数量的活动比赛，但使用[比赛标签](../authoritative/#match-label)查询活动的比赛并根据玩家所需的条件筛选结果，则将提供更相关的比赛和更吸引人的用户体验。

除了比赛 `label`，您还可以按结果的权威状态和[玩家数](#player-count)筛选结果。请参阅[功能参考](../../../server-framework/typescript-runtime/function-reference/#matchList)，了解所有参数。

## 筛选与查询

使用比赛 `label` 字段列出结果有两种方法：精确匹配筛选和查询。

例如，如要列出具有标签 `skill=100-150` 的比赛，精确匹配筛选将如下所示：

{{< code type="server" >}}
```lua
local nk = require("nakama")

local limit = 10
local isAuthoritative = true
local label = "skill=100-150"
local min_size = 0
local max_size = 4
local matches = nk.match_list(limit, isAuthoritative, label, min_size, max_size)

for _, match in ipairs(matches) do
  nk.logger_info(string.format("Match id %s", match.match_id))
end
```
{{< / code >}}

{{< code type="server" >}}
```go
limit := 10
isAuthoritative := true
label := "skill=100-150"
min_size := 0
max_size := 4

if matches, err := nk.MatchList(ctx, limit, isAuthoritative, label, min_size, max_size, ""); err != nil {
    logger.WithField("err", err).Error("Match list error.")
} else {
    for _, match := range matches {
        logger.Info("Match id %s", match.GetMatchId())
    }
}
```
{{< / code >}}

{{< code type="server" >}}
```typescript
function getMatchListings(context: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama) {
  const limit = 10
  const isAuthoritative = true;
  const label = "skill=100-150";
  const minSize = 0;
  const maxSize = 4;
  const matches = nk.matchList(limit, isAuthoritative, label, minSize, maxSize, "");

  matches.forEach(function (match) {
    logger.info("Match id '%s'", match.matchId);
  });
}
```
{{< / code >}}

记住我们是在根据标签的字符串值进行筛选，因此结果将**仅包含**具有**精确**标签 `skill=100-150` 的比赛。不会返回具有标签 `skill=100` 或 `skill=150` 的比赛。 

虽然任何返回的结果都是玩家正在搜索的结果，但如果根本找不到匹配的结果，这可能会让人失望。 

另一种方法是使用查询来列出根据所需条件筛选的现有比赛，在本例中为 `skill` 中的[范围](../query-syntax/#ranges)：

{{< code type="server" >}}
```lua
local nk = require("nakama")

local limit = 10
local isauthoritative = true
local label = ""
local min_size = 0
local max_size = 4
local query = "+label.skill>=100 +label.skill<=150"
local matches = nk.match_list(limit, isauthoritative, label, min_size, max_size, query)

for _, match in ipairs(matches) do
  nk.logger_info(string.format("Match id %s", match.match_id))
end
```
{{< / code >}}

{{< code type="server" >}}
```go
limit := 10
authoritative := true
label := ""
minSize := 0
maxSize := 4
query := "+label.skill>=100 +label.skill<=150"
matches, err := nk.MatchList(ctx, limit, authoritative, label, minSize, maxSize, query)

if err != nil {
    logger.WithField("err", err).Error("Match listings error.")
    return
}

for _, match := range matches {
    logger.Info("Match id %s", match.MatchId)
}
```
{{< / code >}}

{{< code type="server" >}}
```typescript
function findMatch(context: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama) {
  const limit = 10
  const isAuthoritative = true;
  const minSize = 0;
  const maxSize = 4;
  const query = "+label.skill>=100 +label.skill<=150";
  var matches = nk.matchList(limit, isAuthoritative, minSize, maxSize, query);

  matches.forEach(function (match) {
    logger.info("Match id '%s'", match.matchId);
  });
}
```
{{< / code >}}

使用此方法，结果将包含带有介于 100 和 150 之间（包括 100 和 150）的 `skill` 标签的**任何**比赛。 

了解如何使用[查询语法](../query-syntax/)筛选和排序结果。

## 查找或创建

要为用户提供顺畅的游戏体验，如果比赛列表无法返回任何匹配结果，您可以直接为用户创建新的比赛。

使用上述筛选示例：

{{< code type="server" >}}
```lua
local nk = require("nakama")
local function findorcreatematch(limit, label, min_size, max_size)
  local matches = nk.match_list(limit, true, label, min_size, max_size)

  if (#matches > 0) then
    table.sort(matches, function(a, b)
      return a.size > b.size;
    end)
    return matches[1].match_id
  end

  local modulename = "supermatch"
  local initialstate = {}
  local match_id = nk.match_create(modulename, initialstate)
  return match_id
end
```
{{< / code >}}

{{< code type="server" >}}
```go
if matches, err := nk.MatchList(ctx, limit, true, label, min_size, max_size, "*"); err != nil {
    return "", err
} else {
    if len(matches) > 0 {
        sort.Slice(matches, func(i, j int) bool {
          return matches[i].Size < matches[j].Size
        })

        return matches[0].MatchId
    }
}

modulename := "supermatch"

if matchId, err := nk.MatchCreate(ctx, modulename, nil); err != nil {
    return "", err
} else {
    return matchId, nil
}

return "", nil
```
{{< / code >}}

{{< code type="server" >}}
```typescript
function findOrCreateMatch(context: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama): string {
  var matches = nk.matchList(limit, isAuthoritative, label, minSize, maxSize, "");

  // If matches exist, sort by match size and return the largest.
  if (matches.length > 0) {
    matches.sort(function (a, b) {
      return a.size >= b.size ? 1 : -1;
    });
    return matches[0].matchId;
  }

  // If no matches exist, create a new one using the "lobby" module and return it's ID.
  var matchId = nk.matchCreate('supermatch', {});
  return JSON.stringify({ matchId });
}
```
{{< / code >}}

查询比赛时的操作也一样：

{{< code type="server" >}}
```lua
local query = "+label.skill>=100 +label.skill<=150"
local matches = nk.match_list(10, true, "", 2, 4, query)

if #matches > 0 then
  nk.logger_info(matches[0].match_id)
else
  local match_id = nk.match_create("matchname", {})
  nk.logger_info(match_id)
end
```
{{< / code >}}

{{< code type="server" >}}
```go
query := "+label.skill>=100 +label.skill<=150"
matches, err := nk.MatchList(ctx, 1, true, "", 2, 4, query)

if err != nil {
    logger.WithField("err", err).Error("List match error.")
    return
}

if len(matches) > 0 {
    logger.Info(matches[0].MatchId)
} else {
    matchId, err := nk.MatchCreate(ctx, "matchname", nil)

    if err != nil {
        logger.WithField("err", err).Error("Match create error.")
        return
    }

    logger.Info(matchId)
}
```
{{< / code >}}

{{< code type="server" >}}
```typescript
function findOrCreateMatch(context: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama) {
  const query = "+label.skill>=100 +label.skill<=150";
  var matches = nk.matchList(10, true, "", 2, maxSize, query);

  // If matches exist, sort by match size and return the largest.
  if (matches.length > 0) {
    logger.info("Match id '%s'", matches[0].matchId);
  }

  // If no matches exist, create a new one using the "lobby" module and return it's ID.
  var matchId = nk.matchCreate('supermatch', {});
  logger.info(matchId);
}
```
{{< / code >}}

## 示例

### 玩家数

`minSize` 和 `maxSize` 参数可用于仅列出包含指定数量玩家的比赛。这适用于返回人数快满（因此比赛即将开始）的结果。

例如，假设一场比赛将在有 8 名玩家加入后开始，因此我们将仅列出已有 5-7 名玩家的比赛：

{{< code type="server" >}}
```lua
local nk = require("nakama")

local limit = 10
local isAuthoritative = true
local min_size = 5
local max_size = 7
local matches = nk.match_list(limit, isAuthoritative, min_size, max_size)

for _, match in ipairs(matches) do
  nk.logger_info(string.format("Match id %s", match.match_id))
end
```
{{< / code >}}

{{< code type="server" >}}
```go
limit := 10
isAuthoritative := true
min_size := 5
max_size := 7

if matches, err := nk.MatchList(ctx, limit, isAuthoritative, min_size, max_size, ""); err != nil {
    logger.WithField("err", err).Error("Match list error.")
} else {
    for _, match := range matches {
        logger.Info("Match id %s", match.GetMatchId())
    }
}
```
{{< / code >}}

{{< code type="server" >}}
```typescript
function getMatchListings(context: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama) {
  const limit = 10
  const isAuthoritative = true;
  const minSize = 5;
  const maxSize = 7;
  const matches = nk.matchList(limit, isAuthoritative, minSize, maxSize, "");

  matches.forEach(function (match) {
    logger.info("Match id '%s'", match.matchId);
  });
}
```
{{< / code >}}
