ListIssues API labels parameter does AND instead of OR #14100

Open
opened 2025-11-02 11:02:49 -06:00 by GiteaMirror · 4 comments
Owner

Originally created by @wdoekes on GitHub (Feb 5, 2025).

Description

In 024871ade6 the following was added:

--- a/routers/api/v1/repo/issue.go
+++ b/routers/api/v1/repo/issue.go
@@ -43,6 +43,10 @@ func ListIssues(ctx *context.APIContext) {
        //   in: query
        //   description: whether issue is open or closed
        //   type: string
+       // - name: labels
+       //   in: query
+       //   description: comma separated list of labels. Fetch only issues that have any of this labels. Non existent labels are discarded
+       //   type: string
...
                issues, err = models.Issues(&models.IssuesOptions{
                        RepoIDs:  []int64{ctx.Repo.Repository.ID},
                        Page:     ctx.QueryInt("page"),
                        PageSize: setting.UI.IssuePagingNum,
                        IsClosed: isClosed,
                        IssueIDs: issueIDs,
+                       LabelIDs: labelIDs,
                })

(which now looks like this since 1e76a824bc)

+       if len(labelIDs) == 1 && labelIDs[0] == 0 {
+               searchOpt.NoLabelOnly = true
+       } else {
+               for _, labelID := range labelIDs {
+                       if labelID > 0 {
+                               searchOpt.IncludedLabelIDs = append(searchOpt.IncludedLabelIDs, labelID)
+                       } else {
+                               searchOpt.ExcludedLabelIDs = append(searchOpt.ExcludedLabelIDs, -labelID)
+                       }
                }
+       }

These end up in ./modules/indexer/issues/meilisearch/meilisearch.go:

        if options.NoLabelOnly {
                query.And(inner_meilisearch.NewFilterEq("no_label", true))
        } else {
                if len(options.IncludedLabelIDs) > 0 {
                        q := &inner_meilisearch.FilterAnd{}
                        for _, labelID := range options.IncludedLabelIDs {
                                q.And(inner_meilisearch.NewFilterEq("label_ids", labelID))
                        }
                        query.And(q)
                } else if len(options.IncludedAnyLabelIDs) > 0 {
                        query.And(inner_meilisearch.NewFilterIn("label_ids", options.IncludedAnyLabelIDs...))
                }

So, the ListIssues sets the IncludedLabelIDs, not the IncludedAnyLabelIDs option.

There is also a similar API, called SearchIssues, which used to behave the same (in 887a8fe242). But that has been refactored to use IncludedAnyLabelIDs (1e76a824bc and d638067d3c).

  • Now SearchIssues has proper English ("these labels"),
  • and SearchIssues does what it promises (do an OR-search).

It would be nice if ListIssues either:

  • Has the same labels search behaviour,
  • or updates the documentation.

Thanks!
Walter Doekes
OSSO B.V.

Gitea Version

main/7e596bd7a9378cadbbd9efaf9cc622de554e056c

Can you reproduce the bug on the Gitea demo site?

No

Log Gist

No response

Screenshots

No response

Git Version

No response

Operating System

linux

How are you running Gitea?

(running downloaded gitea 1.21.5)

Database

None

Originally created by @wdoekes on GitHub (Feb 5, 2025). ### Description In 024871ade60c619302430a2852018dcbd1b35b79 the following was added: ```diff --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -43,6 +43,10 @@ func ListIssues(ctx *context.APIContext) { // in: query // description: whether issue is open or closed // type: string + // - name: labels + // in: query + // description: comma separated list of labels. Fetch only issues that have any of this labels. Non existent labels are discarded + // type: string ... issues, err = models.Issues(&models.IssuesOptions{ RepoIDs: []int64{ctx.Repo.Repository.ID}, Page: ctx.QueryInt("page"), PageSize: setting.UI.IssuePagingNum, IsClosed: isClosed, IssueIDs: issueIDs, + LabelIDs: labelIDs, }) ``` (which now looks like this since 1e76a824bcd71acd59cdfb2c4547806bc34b3d86) ```diff + if len(labelIDs) == 1 && labelIDs[0] == 0 { + searchOpt.NoLabelOnly = true + } else { + for _, labelID := range labelIDs { + if labelID > 0 { + searchOpt.IncludedLabelIDs = append(searchOpt.IncludedLabelIDs, labelID) + } else { + searchOpt.ExcludedLabelIDs = append(searchOpt.ExcludedLabelIDs, -labelID) + } } + } ``` These end up in `./modules/indexer/issues/meilisearch/meilisearch.go`: ```golang if options.NoLabelOnly { query.And(inner_meilisearch.NewFilterEq("no_label", true)) } else { if len(options.IncludedLabelIDs) > 0 { q := &inner_meilisearch.FilterAnd{} for _, labelID := range options.IncludedLabelIDs { q.And(inner_meilisearch.NewFilterEq("label_ids", labelID)) } query.And(q) } else if len(options.IncludedAnyLabelIDs) > 0 { query.And(inner_meilisearch.NewFilterIn("label_ids", options.IncludedAnyLabelIDs...)) } ``` So, the `ListIssues` sets the `IncludedLabelIDs`, not the `IncludedAnyLabelIDs` option. There is also a similar API, called `SearchIssues`, which _used to behave the same_ (in 887a8fe2422ed783ae0968fccc269bdfb6a39595). But that has been refactored to use `IncludedAnyLabelIDs` (1e76a824bcd71acd59cdfb2c4547806bc34b3d86 and d638067d3cb0a7f69b4d899f65b9be4940bd3e41). - Now SearchIssues has proper English ("these labels"), - and SearchIssues does what it promises (do an OR-search). It would be nice if ListIssues either: - Has the same labels search behaviour, - or updates the documentation. Thanks! Walter Doekes OSSO B.V. ### Gitea Version main/7e596bd7a9378cadbbd9efaf9cc622de554e056c ### Can you reproduce the bug on the Gitea demo site? No ### Log Gist _No response_ ### Screenshots _No response_ ### Git Version _No response_ ### Operating System linux ### How are you running Gitea? (running downloaded gitea 1.21.5) ### Database None
GiteaMirror added the topic/apitype/bug labels 2025-11-02 11:02:49 -06:00
Author
Owner

@wdoekes commented on GitHub (Feb 5, 2025):

P.S. Temporary workaround for our use case is thus:

  • use the repo-wide search with a token that only has access to the one repo
  • and then to the OR-labels search there
@wdoekes commented on GitHub (Feb 5, 2025): P.S. Temporary workaround for our use case is thus: - use the repo-wide search with a token that only has access to the one repo - and then to the OR-labels search there
Author
Owner

@wxiaoguang commented on GitHub (Feb 5, 2025):

Hmm, I think "AND" is the expected (better) behavior.

For example: when a user searches: LabelA, LableB

  • they could always get "OR" results by query LableA, then query LabelB (just two queries)
  • they could only get "AND" results by using the current behavior: LabelA & LableB

So maybe it should "update the documentation"?

@wxiaoguang commented on GitHub (Feb 5, 2025): Hmm, I think "AND" is the expected (better) behavior. For example: when a user searches: LabelA, LableB * they could always get "OR" results by query LableA, then query LabelB (just two queries) * they could only get "AND" results by using the current behavior: LabelA & LableB So maybe it should "update the documentation"?
Author
Owner

@wdoekes commented on GitHub (Feb 5, 2025):

Well. You'll always disappoint one group of users. You could also certainly argue for the inverse and let people filter their results. It depends on what one considers the costliest: is filtering a resultset worse than having to do two queries and merge the results?

Is there a reason why there is an OR-search in the SearchIssues API now? And what were the considerations when the feature(s) were added?

@wdoekes commented on GitHub (Feb 5, 2025): Well. You'll always disappoint one group of users. You could also certainly argue for the inverse and let people filter their results. It depends on what one considers the costliest: is filtering a resultset worse than having to do two queries and merge the results? Is there a reason why there is an OR-search in the SearchIssues API now? And what were the considerations when the feature(s) were added?
Author
Owner

@wxiaoguang commented on GitHub (Feb 5, 2025):

TBH: no idea ..... I am not quite familiar with the "search" logic (some code/decisions are before I started coding in Gitea), maybe some people who have more experiences could help.

@wxiaoguang commented on GitHub (Feb 5, 2025): TBH: no idea ..... I am not quite familiar with the "search" logic (some code/decisions are before I started coding in Gitea), maybe some people who have more experiences could help.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/gitea#14100