feat(issue-search): support query syntax #9109
Labels
No labels
arch
riscv64
backport/v1.19
backport/v1.20
backport/v1.21/forgejo
backport/v10.0/forgejo
backport/v11.0/forgejo
backport/v12.0/forgejo
backport/v13.0/forgejo
backport/v14.0/forgejo
backport/v7.0/forgejo
backport/v8.0/forgejo
backport/v9.0/forgejo
breaking
bug
bug
confirmed
bug
duplicate
bug
needs-more-info
bug
new-report
bug
reported-upstream
code/actions
code/api
code/auth
code/auth/faidp
code/auth/farp
code/email
code/federation
code/git
code/migrations
code/packages
code/wiki
database
MySQL
database
PostgreSQL
database
SQLite
dependency-upgrade
dependency
certmagic
dependency
chart.js
dependency
Chi
dependency
Chroma
dependency
citation.js
dependency
codespell
dependency
css-loader
dependency
devcontainers
dependency
dropzone
dependency
editorconfig-checker
dependency
elasticsearch
dependency
enmime
dependency
F3
dependency
ForgeFed
dependency
garage
dependency
Git
dependency
git-backporting
dependency
Gitea
dependency
gitignore
dependency
go-ap
dependency
go-enry
dependency
go-gitlab
dependency
Go-org
dependency
go-rpmutils
dependency
go-sql-driver mysql
dependency
go-swagger
dependency
go-version
dependency
go-webauthn
dependency
gocron
dependency
Golang
dependency
goldmark
dependency
goquery
dependency
Goth
dependency
grpc-go
dependency
happy-dom
dependency
Helm
dependency
image-spec
dependency
jsonschema
dependency
KaTeX
dependency
lint
dependency
MariaDB
dependency
Mermaid
dependency
minio-go
dependency
misspell
dependency
Monaco
dependency
PDFobject
dependency
playwright
dependency
postcss
dependency
postcss-plugins
dependency
pprof
dependency
prometheus client_golang
dependency
protobuf
dependency
relative-time-element
dependency
renovate
dependency
reply
dependency
ssh
dependency
swagger-ui
dependency
tailwind
dependency
temporal-polyfill
dependency
terminal-to-html
dependency
tests-only
dependency
text-expander-element
dependency
urfave
dependency
vfsgen
dependency
vite
dependency
Woodpecker CI
dependency
x tools
dependency
XORM
Discussion
duplicate
enhancement/feature
forgejo/accessibility
forgejo/branding
forgejo/ci
forgejo/commit-graph
forgejo/documentation
forgejo/furnace cleanup
forgejo/i18n
forgejo/interop
forgejo/moderation
forgejo/privacy
forgejo/release
forgejo/scaling
forgejo/security
forgejo/ui
Gain
High
Gain
Nice to have
Gain
Undefined
Gain
Very High
good first issue
i18n/backport-stable
impact
large
impact
medium
impact
small
impact
unknown
Incompatible license
issue
closed
issue
do-not-exist-yet
issue
open
manual test
Manually tested during feature freeze
OS
FreeBSD
OS
Linux
OS
macOS
OS
Windows
problem
QA
regression
release blocker
Release Cycle
Feature Freeze
release-blocker
v7.0
release-blocker
v7.0.1
release-blocker
v7.0.2
release-blocker
v7.0.3
release-blocker
v7.0.4
release-blocker
v8.0.0
release-blocker/v9.0.0
run-all-playwright-tests
run-end-to-end-tests
test
manual
test
needed
test
needs-help
test
not-needed
test
present
untested
User research - time-tracker
valuable code
worth a release-note
User research - Accessibility
User research - Blocked
User research - Community
User research - Config (instance)
User research - Errors
User research - Filters
User research - Future backlog
User research - Git workflow
User research - Labels
User research - Moderation
User research - Needs input
User research - Notifications/Dashboard
User research - Rendering
User research - Repo creation
User research - Repo units
User research - Security
User research - Settings (in-app)
No milestone
No project
No assignees
7 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo/forgejo!9109
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "snematoda/issue-search-syntax-filters"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
List of currently supported filters:
is:open(or-is:closed)is:closed(or-is:open)is:allauthor:<username>assignee:<username>review:<username>mentions:<username>modified:[>|<]<date>, where<date>is the last update date.sort:<by>:[asc|desc], where<by>is amongRelease notes
dfe7b8bb0e264b618df4264b618df46c014113faThank you very much. Would it make sense to allow differentiating closed and merged PRs? E.g.
is:closed includes closed issues, closed PRs and merged PRs
is:merged includes merged PRs
is:rejected includes PRs which are closed without merging
I don't know if the term "rejected" sits right with me. Maybe
-is:mergedandis:closedtogether is good enough until we have evidence this is a common need.@fnetX wrote in #9109 (comment):
is:mergedand-is:mergedsounds like a fine addition!Unfortunately, there is no field indicating the status among
IndexerData... I would prefer taking on that challenge on a different PR as a part 2 of this one ;)Further, I'm a little concerned that "before" and "after" refer to the updated dates. Changing the behaviour afterwards might also be bad. Is another platform doing it this way?
I could imagine that something like the following variants could be more intuitive:
modified:<2025-03-28andmodified:>2025-03-28modified:*-2025-03-28,modified:2025-03-28-*andmodified:2025-03-28-2025-04-19for a range (although the double usage of hypen is unfortunate here)In the future, the same behaviour could be added for
created:,closed:,merged:or something like this if we want.@snematoda wrote in #9109 (comment):
What's the purpose of all those variations? I don't really see the need. And I do expect people to get confused (what should
-is:open is:all is:opendo?)I'd say:
is:openandis:closedis:is present, show all entriesUnless you're planning to add more fine-grained statuses, like
is:locked. Exclusion does make sense once you have more than two states.@snematoda wrote in #9109 (comment):
Having a different set of prefixes (
recent/least,near/far, ...) for every field is rather confusing. I thinksort:<by>:ascorsort:asc:<by>would be more intuitive and easier to remember. It also avoids ambiguities like "doesleastupdatemean 'least amount of updates' or 'least recently updated'".@snematoda wrote in #9109 (comment):
You could copy Bleve's syntax to support more than one date field:
created:>2016updated:<2025-08-01Other potential fields:
participated:<user>type:issue/type:prlabel:bug/confirmeddue-in:10dAs for what sparked this, additional things that Bleve/Elasticsearch are capable of:
titleanddescription@fnetX wrote in #9109 (comment):
That looks much more clearer! Will change!
Wouldn't,
modified:>2025-03-28 modified:<2025-04-19suffice in this case :)@sclu1034 wrote in #9109 (comment):
Currently for this case only the last one would be considered... in the above example it would be
is:open...One issue with this, is that the dropdowns and switches are still present, the query syntax works along with them.
I'm afraid whether showing all the entries would conflict with the current default of showing only the open requestes unless a specific option is specified...
is:open is:closed=>is:alldoes sound logical :)Will change, i still prefer retaining
is:all... not really a must but it's much shorter to type ;)@sclu1034 wrote in #9109 (comment):
Sound great, Will change!
Similar to the
is:mergedsuggestion above, the creation date is sadly not stored on the indexer... so i'll putcreated:on the part 2 pile :)@sclu1034 wrote in #9109 (comment):
The search box is still divided into two so it does not make much sense to add these filters now... Might be best to them when a unified search box is added :D
@snematoda wrote in #9109 (comment):
The default query could be adjusted to include whatever is needed to be in sync with the default state of the switches/dropdown. GitHub, similarly, has
is:openin their default query string.@snematoda wrote in #9109 (comment):
It only really makes sense as an exception as long as
openandcloseare the only two states. If others likeis:mergedoris:lockedare planned (even just for a future addition), I would keepis:openandis:closemutually exclusive to make sure they fit in when the rest is added.@ -116,0 +162,4 @@// [-]sort:<by>,// for example, sort:created / -sort:commentscase token.IsOf("sort:"):o.SortBy = parseSortBy(token.Term[5:], token.Kind != BoolOptNot)Using
-for the sort direction is really confusing in my opinion. Especially when the same symbol is already used for a completely different meaning in the same query.Does an extra part in the string, like
sort:asc:<by>, not work?I suppose that works much better :)
Removed
after:andbefore:in favor ofmodified::)Current syntax for sort:+sort:<by>,sort:<by>=> asc-sort:<by>=> descWhere,<by>is one of,createdcommentsupdateddeadline[...] => scorewhile not on the current short term i do hope to follow up the PR... perhaps it's best left as-is...
A fair idea, but a bit of a sticky solution imho as it does require a bit of client side js :)
@snematoda wrote in #9109 (comment):
Populating the
valueattribute in the template should be enough.@sclu1034 wrote in #9109 (comment):
gave it a go yesterday, i just couldn't get it to a state i was happy with... :/
dropping it for now...
For some reason, the latest CI runs are broken. According to https://codeberg.org/forgejo/forgejo/actions?workflow=&actor=0&status=5, they have been pushed by Ghost, but why does it prevent them from running? I can't kick them manually.
@fnetX wrote in #9109 (comment):
My bad 🙈... #9371 has the relevant details...
b7e8e3e918174718f7866ba2a7738b45817a26e545817a26e556634595505663459550c0ee8900e5c0ee8900e56209f49b4d6209f49b4db67a92656bWIP: feat(issue-search): support query syntaxto feat(issue-search): support query syntax@fnetX Would this benefit from a modal with a description of the query syntax?
Where does that come from?
The following is a preview of the release notes for this pull request, as they will appear in the upcoming release. They are derived from the content of the `release-notes/9109.md` file, if it exists, or the title of the pull request. They were also added at the bottom of the description of this pull request for easier reference.This message and the release notes originate from a call to the release-notes-assistant.
Release notes
Some minor comments, the code looks quite good and not complicated at all for this great feature great job!
@ -164,3 +160,1 @@if len(tokens) > 0 {q := bleve.NewBooleanQuery()for _, token := range tokens {if len(options.Tokens) != 0 {This if condition can be dropped it seems, if
len(options.Tokens) == 0then the loop is not run.Nice catch! fixed...
@ -187,2 +187,3 @@queries = append(queries, q)}// TODO: replace with following with filters// https://github.com/blevesearch/bleve/pull/2220#9780 this now available.
Updated :)
@ -82,3 +64,2 @@cond = builder.Or(builder.Eq{"`index`": issueID},cond,db.BuildCaseInsensitiveLike("issue.name", options.Tokens[0].Term),It seems that this loop will now generate quite a complex query when the only variant is
db.BuildCaseInsensitiveLike("content", token.Term). Could the loop be reduced to that?options.Tokens[0]was a mistake on my part... my bad 🫣The SQL query sadly still remains complex more than what i want it to be...
@Gusted wrote in #9109 (comment):
Yes, I think this would be a good case in the spirit of #8662. It makes sense to have it in-app rather than in an external documentation.
b67a92656b6c6cb3a9b66c6cb3a9b62b3090ed492b3090ed4943959ce56eCI failure looks related.
@fnetX wrote in #9109 (comment):
What would be a good place to add the help icon? The horizontal line that the search bar is on is already quite... packed
Hmm, that's a good question. Intuitively, I would have added it to the line after the search icon. On the other hand, it basically contains some of the filters that are added below, so a position before the filter buttons could also make sense ("these filters and switches can also be controlled via the search bar").
@Gusted wrote in #9109 (comment):
Yes... after a bit of poking around.... seems like bleve's new
Filterquery is very flaky for slices...?Passes fine sometimes, but fails with count '1' if you run it a few times... will report this upstream and
WIP:this pr in the meantime...feat(issue-search): support query syntaxto WIP: feat(issue-search): support query syntaxWaiting for the v2.5.5 release now :)
https://github.com/blevesearch/bleve/pull/2239
EDIT: Tests pass fine now :)
43959ce56eff66f9ff7a@fnetX wrote in #9109 (comment):
How about a help icon along with the search bar?
fa1ad1a5e60a3a387300@snematoda Yes, this is where I'd have placed it. I expected it to be a challenge on mobile, but the mobile view seems to place the search bar on its own line anyway.
WIP: feat(issue-search): support query syntaxto feat(issue-search): support query syntax@ -59,0 +60,4 @@"repo.issues.filter_assignee_hint": "Filter by assigned user","repo.issues.filter_mention_hint": "Filter by mentioned user","repo.issues.filter_modified_hint": "Filter by last modified date","repo.issues.filter_sort_hint": "Filter by sort type; created/comments/updated/deadline",Pretty sure the former is called
due datein the ui but deadline as one word seems fine. Also, you might have wanted to use:I'd like to propose the following (clearer) key format:
issues.filter.X.hint@ -93,6 +98,7 @@"migrate.forgejo.description": "Migrate data from codeberg.org or other Forgejo instances.","repo.issue_indexer.title": "Issue Indexer","search.milestone_kind": "Search milestones…","search.syntax": "Search Syntax",The general guideline is to not use
newstitle case anywhere.@ -21,0 +30,4 @@<table class="tw-table-auto"><tbody>{{range $filter, $expl :=dict691dd023ff/modules/templates/helper.goIt would be nice to have a dedicated function for dictionaries where the values are msgids, in order to be able to handle those in
lint-locale-usage.@ -21,0 +39,4 @@"review:<username>" "repo.issues.filter_mention_hint""mention:<username>" "repo.issues.filter_mention_hint""sort:<by>:[asc|desc]" "repo.issues.filter_sort_hint""modified:[>|<]<date>" "repo.issues.filter_mention_hint"}}repo.issues.filter_mention_hintlooks wrong here.Yeah, there are in total three of these in total in the list
🙈 my bad...
@ -19,2 +19,4 @@{{end}}</div>{{if not .PageIsMilestones}}<a class="ui icon tw-px-4" id="search-syntax-button">{{svg "octicon-question"}}</a>We don't seem to have a class for such button yet, so it's fine to have this. You may want to add
tw-py-2to further increase clickable area.As well as
gap: 0.5rem;to.list-header-search. It wasn't ready to have multiple items in it but now it will.@ -21,0 +24,4 @@<article><header><span>{{ctx.Locale.Tr "search.syntax"}}</span><button class="ui button icon cancel tw-ml-auto">{{svg "octicon-x"}}</button>Other dialogs use a text button at the bottom, best to stick to that for consistency.
@ -116,0 +190,4 @@case token.IsOf("author:"):userNames = append(userNames, token.Term[7:])userFilter = append(userFilter, userFilterAuthor)case token.IsOf("assign:"):I wonder if this should be
assignedso it reads better. It is longer though.blame my laziness for the short tags... will change to
assignee:to be compatible with github :)@ -116,0 +196,4 @@case token.IsOf("review:"):userNames = append(userNames, token.Term[7:])userFilter = append(userFilter, userFilterReview)case token.IsOf("mention:"):Ditto, but maybe
mentions?Looks pretty good overall!
0a3a38730008fc1bb324The syntax seems to also apply on these:
/org/<name>/pulls?/pullsWhich is really cool but it also means they lack the hint button and the dialog. Best to move it to a reusable template.
The parts affecting
lint-locale-usageare okay.08fc1bb324b5514e8c04@0ko wrote in #9109 (comment):
Nice catch! added :)
tw-gap-2was not copied to the other template, causing a minor inconsistency.As suggested in #9109 (comment), it's better to move this property to the actual CSS as it is easy to introduce such inconsistencies with Tailwind. I checked all usages of class
list-header-searchand it should not cause issues in any other areas it is used in.,b5514e8c04905485be7cBackend code looks great, thanks!
@ -236,7 +237,14 @@ function initArchivedLabelFilter() {});}function initSearchSyntaxModal() {This code can be avoided, you can add the
show-modelclass and adddata-modal="#search-syntax-modal".905485be7ce2c491a874e2c491a874f1e480eb77Thank you!