Skip to content

Add multi-label support to Find box for number fields#6964

Open
rvisser7 wants to merge 19 commits intoLMFDB:mainfrom
rvisser7:new_jump_box
Open

Add multi-label support to Find box for number fields#6964
rvisser7 wants to merge 19 commits intoLMFDB:mainfrom
rvisser7:new_jump_box

Conversation

@rvisser7
Copy link
Copy Markdown
Member

@rvisser7 rvisser7 commented Apr 10, 2026

I've had a go at implementing issue #6882 in this PR, just for number fields for now. It essentially follows the SneakyBox approach suggested by @roed314 .

As always, any comments/feedback are very welcome! 🙂 At present, this is only implemented for number fields, but I'll hopefully extend this to other sections soon.

How it works:

  • A function multi_entry_jump_search has been added to search_wrapper.py. This is meant to be a generic handler which parses a comma-separated list of entries (e.g. could be labels/names/polynomials/equations) given as an input string in the jump box. Each entry is processed using a custom section-specific parser function parse_entry. (e.g. for number fields, this is just nf_string_to_label).

    If any of the entries are unable to be parsed, it flashes an info message on the number of invalid entries. If all entries are invalid, it flashes an error message and returns the usual home search page.

  • Also in search_wrapper.py, a function parse_labels has been added to convert a "?labels=..." URL query into a database query of the form {"$in": [...]} on the label column.

  • I've tried to keep the section-specific code to a minimum. In particular, the only update to number_field.py is some code at the beginning of number_field_jump which first runs the generic multi_entry_jump_search parser, and setting the label_knowl argument (used to define the labels SneakyBox).

Examples for testing:

For now, I've just put this as a draft, just to get any preliminary feedback on whether this looks ok, or whether this should maybe be implemented in a different way. If the editors are happy with the above implementation, I can then implement this for all other sections of the LMFDB where we'd like to support a multi-label search in the "Find" jump box. :)

@rvisser7 rvisser7 marked this pull request as draft April 10, 2026 23:32
Comment thread lmfdb/utils/search_wrapper.py Outdated
if not labels_input or not hasattr(table, "_label_col"):
return

labels, seen = [], set()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you could just do labels = list(set(label.strip() for label in labels_input.split(","))).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, done!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this doesn't matter too much, but would it maybe make more sense for parse_labels to instead be in the utils/search_parsing.py file?

Comment thread lmfdb/utils/search_wrapper.py Outdated
not_parsed, not_found = 0, 0
for entry in entries:
try:
label = parse_entry(entry)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jwj61 expressed concern about polredabs getting called many times. I wonder if you could also add a progressive timeout here, where you stop if the total amount of parsing time surpasses an amount determined by a keyword.

Copy link
Copy Markdown
Member Author

@rvisser7 rvisser7 Apr 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, of course, thanks - I forgot about this!

I've added a timer to this for loop. If the timer hits the value set by time_limit (I've put a default of 30 seconds), then it flashes an error and returns the index page. At the moment, the timer is only checked between each entry being parsed, so I am assuming that parsing at least a single entry won't take too long.

Comment thread lmfdb/utils/search_wrapper.py Outdated
- ``index_endpoint`` -- the URL for the index homepage for this section
- ``input_key`` -- the dictionary key for the jump search box (default: "jump")
- ``labels_jey`` -- the dictionary key for the labels search query (default: "labels")
- ``sep`` -- A string used as the seperator for parsing the jump box input (default: ",")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you can provide sep as a function, defaulting to lambda x: re.split(",", x). Then you can allow Q(sqrt2,sqrt3) for a field name even though it has a comma in it by making a more complicated splitting function.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is a great suggestion!

I've had a go at writing a function split_top_level_commas, currently placed just above multi_entry_jump_search. This takes some input string and returns a list of substrings which only splits on commas which are not inside any parentheses/brackets/braces. Since this would probably give the intended behaviour for most sections (not just number fields), I've made this the default separator function.

Comment thread lmfdb/utils/search_wrapper.py Outdated
- ``info`` -- the info dictionary passed in from front end
- ``parse_entry`` -- a custom function which converts a string (e.g. polynomial, equation, nickname etc) to be parsed into label
- ``label_exists`` -- a custom function which determines whether a given label exists in the database
- ``index_endpoint`` -- the URL for the index homepage for this section
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

technically this is the input to url_for, not a url itself.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, fixed!

@rvisser7
Copy link
Copy Markdown
Member Author

Just for fun, maybe I can also mention another nice consequence of this PR: this also provides a convenient way get a search page for essentially any parametrised family of fields directly via the Find box (or the Labels box). So in particular, I think this also at least gives some partial progress towards issue #6948 🙂

E.g. to obtain a search results page for the first few cyclotomic fields (ordered by degree), we can just copy-paste the Python output of ",".join("Qzeta"+str(n) for n in range(100)) into the Find box. Or similarly, to get a search for pure cubic fields, we just paste the output of ",".join("x^3-"+str(n) for n in range(1000)) .

Just for convenience, I've given some links to search pages for some of the families mentioned in #6948 below. To estimate the polredabs cost, I've also given some rough estimates on the time taken for each page to load using the "jump" link, (measured using the Legendre server):

  • Cyclotomic fields $\mathbb{Q}(\zeta_n)$, for $n \leq 100$ (jump, labels). Takes < 1 sec to load.

  • Maximal totally real subfields $\mathbb{Q}(\zeta_n)^+$ of cyclotomics, for $n \leq 100$ (jump, labels). Takes < 1 sec to load.

  • Pure cubic fields $\mathbb{Q}(\sqrt[3]{a})$ for $0 \leq a &lt; 1000$ (jump, labels). Takes ~11 sec to load.

  • Pure quartic fields $\mathbb{Q}(\sqrt[4]{a})$ for $0 \leq a &lt; 1000$ (jump, labels). Takes ~12 sec to load.

  • Simplest cubic fields $\mathbb{Q}[x]/(x^3 - ax^2 - (a+3)x - 1)$ for $0 \leq a &lt; 1000$ (jump, labels). Takes ~11 sec to load.

  • Ennola's cubic fields $\mathbb{Q}[x]/(x^3 + (a-1)x^2 - ax - 1)$ for $0 \leq a &lt; 1000$: (jump, labels). Takes ~10 sec to load.

@rvisser7 rvisser7 marked this pull request as ready for review April 12, 2026 16:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants