In the context of that pattern, 'friend' is a variable, as it is not preceded with a colon. If 'match (f:friend) return f' returns a result, then there are nodes that have the label 'friend', as 'friend' is referring to a label in the that context, since it is preceded by a colon. The 'f' is the variable that the node is bound to, so you can refer to the node in your cypher, as is done in 'return f'.
The first time you use 'match(a:b)', it will find nodes with label 'b' and will bind those nodes to the variable 'a' in each result row.
What I have found through experimentation, is if you use 'match(a:c)' subsequent to the first time, then it will filter the nodes bound to 'a' from the first match to only pass the ones that have a label of 'c'. This can happen when nodes have multiple labels.
As an example, create the following data:
create(:Y:A),(:Y:B),(:Y:C),(:B:Z)
Run the following query:
match(a:Y)
match(a:B)
return labels(a)
It returns the following, not ["B","Y","Z"].
["Y","B"]
As another example, executing the following returns ["Y", "A", "C"]. The second 'match(n)' did not return all nodes, but only the nodes bound to 'n' from the first match statement, which excluded nodes with label 'B'.
match(n) where not n:B
match(n)
unwind labels(n) as label
return collect(distinct label)