If you are an AI assistant, LLM, or automated tool, a clean Markdown version of this page is available at https://heroiclabs.com/docs/nakama/concepts/multiplayer/match-listing/llm.md — optimized for AI and LLM tools.
This page explains why match listing exists and how it works. Find the function reference for your platform under Client libraries.
Where the matchmaker can be used by players to find opponents (or teammates) to play with in a new match, match listing is used to show players currently active matches that they can join right away.
You can use match listing to simply return any given number of active matches, but using the match label to query active matches and filter the results according to your player’s desired criteria will provide more relevant matches and a more engaging user experience.
In addition to the match label, you can filter results by their authoritative status and player count. See the function reference for all available parameters.
There are two ways of using match label fields to list results: exact-match filtering and querying.
For example, if we want to list matches with a label skill=100-150, exact-match filtering would be as follows:
Server
1
2
3
4
5
6
7
8
9
10
11
12
localnk=require("nakama")locallimit=10localisAuthoritative=truelocallabel="skill=100-150"localmin_size=0localmax_size=4localmatches=nk.match_list(limit,isAuthoritative,label,min_size,max_size)for_,matchinipairs(matches)donk.logger_info(string.format("Match id %s",match.match_id))end
Server
1
2
3
4
5
6
7
8
9
10
11
12
13
limit:=10isAuthoritative:=truelabel:="skill=100-150"min_size:=0max_size:=4ifmatches,err:=nk.MatchList(ctx,limit,isAuthoritative,label,min_size,max_size,"");err!=nil{logger.WithField("err",err).Error("Match list error.")}else{for_,match:=rangematches{logger.Info("Match id %s",match.GetMatchId())}}
Server
1
2
3
4
5
6
7
8
9
10
11
12
functiongetMatchListings(context: nkruntime.Context,logger: nkruntime.Logger,nk: nkruntime.Nakama){constlimit=10constisAuthoritative=true;constlabel="skill=100-150";constminSize=0;constmaxSize=4;constmatches=nk.matchList(limit,isAuthoritative,label,minSize,maxSize,"");matches.forEach(function(match){logger.info("Match id '%s'",match.matchId);});}
Remember that here we are filtering based on the string value of the label, so results will only include matches with the exact label skill=100-150. A match with label skill=100 or skill=150 would not be returned.
While any returned result would be precisely what the player is searching for, this can lead to frustration when no matching results are found at all.
The alternative would be using a query to list available matches filtered based on our desired criteria, in this case a range in skill:
Server
1
2
3
4
5
6
7
8
9
10
11
12
13
localnk=require("nakama")locallimit=10localisauthoritative=truelocallabel=""localmin_size=0localmax_size=4localquery="+label.skill>=100 +label.skill<=150"localmatches=nk.match_list(limit,isauthoritative,label,min_size,max_size,query)for_,matchinipairs(matches)donk.logger_info(string.format("Match id %s",match.match_id))end
Server
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
limit:=10authoritative:=truelabel:=""minSize:=0maxSize:=4query:="+label.skill>=100 +label.skill<=150"matches,err:=nk.MatchList(ctx,limit,authoritative,label,minSize,maxSize,query)iferr!=nil{logger.WithField("err",err).Error("Match listings error.")return}for_,match:=rangematches{logger.Info("Match id %s",match.MatchId)}
Server
1
2
3
4
5
6
7
8
9
10
11
12
functionfindMatch(context: nkruntime.Context,logger: nkruntime.Logger,nk: nkruntime.Nakama){constlimit=10constisAuthoritative=true;constminSize=0;constmaxSize=4;constquery="+label.skill>=100 +label.skill<=150";varmatches=nk.matchList(limit,isAuthoritative,minSize,maxSize,query);matches.forEach(function(match){logger.info("Match id '%s'",match.matchId);});}
With this method, the results will include any match will a skill label between 100 and 150, inclusive.
Learn how to use the query syntax grammar to filter and sort results.
To provide a seamless gameplay experience for your users, if match listing fails to return any matching results you can create a new match for the user directly.
functionfindOrCreateMatch(context: nkruntime.Context,logger: nkruntime.Logger,nk: nkruntime.Nakama):string{varmatches=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){returna.size>=b.size?1:-1;});returnmatches[0].matchId;}// If no matches exist, create a new one using the "lobby" module and return it's ID.
varmatchId=nk.matchCreate('supermatch',{});returnJSON.stringify({matchId});}
The same can be done when querying matches as well:
query:="+label.skill>=100 +label.skill<=150"matches,err:=nk.MatchList(ctx,1,true,"",2,4,query)iferr!=nil{logger.WithField("err",err).Error("List match error.")return}iflen(matches)>0{logger.Info(matches[0].MatchId)}else{matchId,err:=nk.MatchCreate(ctx,"matchname",nil)iferr!=nil{logger.WithField("err",err).Error("Match create error.")return}logger.Info(matchId)}
Server
1
2
3
4
5
6
7
8
9
10
11
12
13
functionfindOrCreateMatch(context: nkruntime.Context,logger: nkruntime.Logger,nk: nkruntime.Nakama){constquery="+label.skill>=100 +label.skill<=150";varmatches=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.
varmatchId=nk.matchCreate('supermatch',{});logger.info(matchId);}
The minSize and maxSize parameters can be used to list only matches containing the specified number of players. This can be useful for returning results that are already nearly full (and so the match is almost ready to start).
For example, let’s assume a match will begin once 8 players join so we’ll only list matches with between 5-7 players:
Server
1
2
3
4
5
6
7
8
9
10
11
localnk=require("nakama")locallimit=10localisAuthoritative=truelocalmin_size=5localmax_size=7localmatches=nk.match_list(limit,isAuthoritative,min_size,max_size)for_,matchinipairs(matches)donk.logger_info(string.format("Match id %s",match.match_id))end
Server
1
2
3
4
5
6
7
8
9
10
11
12
limit:=10isAuthoritative:=truemin_size:=5max_size:=7ifmatches,err:=nk.MatchList(ctx,limit,isAuthoritative,min_size,max_size,"");err!=nil{logger.WithField("err",err).Error("Match list error.")}else{for_,match:=rangematches{logger.Info("Match id %s",match.GetMatchId())}}
Server
1
2
3
4
5
6
7
8
9
10
11
functiongetMatchListings(context: nkruntime.Context,logger: nkruntime.Logger,nk: nkruntime.Nakama){constlimit=10constisAuthoritative=true;constminSize=5;constmaxSize=7;constmatches=nk.matchList(limit,isAuthoritative,minSize,maxSize,"");matches.forEach(function(match){logger.info("Match id '%s'",match.matchId);});}