This article takes a long-form look at how searches in Bubble work.
For a more concise, technical list of settings, constraints, and operators, see our core reference entry on searches.
Reference: Searching
Dynamic expressions: This article covers different dynamic expressions. If you're new to dynamic expressions, we recommend reading the article below first.
Article: Dynamic expressions
Once you've added and updated data in your database, you'll need a way to find that data and display it around your app. This article covers how searching works, from a basic query to sorting, isolating a single record, and the different data sources you can pull from.
Doing a search
Whenever you need to find data in the database, you perform a search using the Do a search for data source¹. This sets up a dynamic query with specific constraints, and Bubble returns all things of that data type that match. You can search for one data type at a time, such as User.
Say you want to find all users named John. First, set the Type of content to User, then pick Do a search for in the Data source dropdown.
Then add a constraint that tells Bubble to return only users whose name is John. The result is always a list, even when it contains just one thing.
This is how database queries work at their core: you tell Bubble what kind of data to search for, then give it one or more constraints that each thing in the returned list has to match. You can use a search in all sorts of places:
To display results on a screen
As part of a workflow, for example to make changes to one or more things
As part of a conditional expression²
Data sources like Do a search for are one of the building blocks of dynamic expressions. To read more about working with expressions, see the article below.
Article: Dynamic expressions
Static and dynamic constraints
In the example above, the constraint was a static value: the name John. You can also set a constraint as a dynamic value, so it changes based on something in your app.
For example, instead of a fixed name, you could point the constraint at the value of an input field. That lets your users type a name and search the database for matching users.
Element data sources using Do a search for stay synced with the database in real time. Any change in the database, even one made by another user, shows up in your app right away, with no need to manually refresh the search.
The exception is a search that was initially fetched in a workflow.
Display name
By default, a dynamic expression shows as the expression itself, such as Do a search for. You can optionally give it a more descriptive label, like "Search for John". The label doesn't change how the search works, it just helps keep your app organized and easy to review.
To change the display name, click on the expression and edit the field Display name.
Sorting the results
Sometimes you'll want to sort the results a particular way, like showing users alphabetically or tasks by priority or deadline. Sorting is useful both for displaying a list and for finding one specific record. For example, to load the last user created in your database, you can sort the list by creation date and then isolate the newest one with the first item or last item operator, depending on the sort order.
Sorting on the search directly
You can set the sort order directly when you perform the search.
Set the sort order in the search itself using the Sorting section. Here, users are sorted by last name in ascending order, since Descending order is set to "no".
Sorting with an operator
In some cases you'll be working with a list that isn't loaded from a search, or you'll need to apply sorting after another operator in the expression.
Applying sorting as an operator (with examples)
Applying sorting as an operator (with examples)
When you add sorting as an operator instead of on the search itself, the sorting is applied on the list that Do a search for returns. In other words, the search runs first and hands back its results, and only then does the sorted operator reorder them. The order of operations is what makes this useful: any step that happens between the search and the sort, like filtering, merging, or combining lists, is reflected in the final order. This comes in handy in a few situations:
Sorting a merged list. You combine two searches with
:merged with, then sort the whole thing. Each search sorts independently, so the combined list needs sorting applied after the merge.Sorting a list stored on a field. A field that holds a list of things (like a user's list of favorite blog posts) has no search to sort. You sort the list after retrieving it.
Sorting another element's data. When your data source is another repeating group's list rather than a fresh search, sorting happens on that referenced list.
Sorting a list that came from an API call. Data returned by the API Connector isn't a database search, so any ordering has to be applied to the returned list afterward.
Sorting after
:intersect with. When you narrow two lists down to their shared items, the intersection is a new list that you then sort.Re-sorting a list in a custom state. If you've stored a list in a custom state, sorting it for display happens after you pull it back out of the state.
Sorting a list built through
:plus itemor:minus item. When you've added or removed individual items from a list, the modified list is sorted afterward.
For those cases, use the sorted operator:
Add the sorted operator to a search by typing "sort" and selecting it from the operator list.
Lists versus single things
Bubble handles database records in two ways: as a single item, or as a list. Understanding this distinction matters, because the two are treated differently. When you load data into container elements³, for example, a group expects a single thing, while a repeating group or table (web) or mobile lists expects a list.
A search always returns a list, even when only one thing matches. In that case it's a list with a count of one, but it's still a list.
Loading a single record from a list
When a data source returns a list, like Do a search for does, any Bubble element⁴ or operator⁵ that expects a single item will flag an error in the issue tracker⁶. To resolve this, you tell Bubble to load just one record from the list by adding an operator to the expression.
Operator | What it returns |
First item | The first item in the list. Which one that is depends on how the list is sorted (by creation date, by default). |
Last item | The last item in the list. Which one that is depends on how the list is sorted (by creation date, by default). |
Random item | A pseudorandom⁷ item from the list. |
Item # | A single item at the index number you specify, such as Item 5. This operator requires you to enter a number. |
Combining search constraints with the first item operator often gets you to the exact thing you're after. For example, you could search users with the Email field as a constraint. Since emails are unique, providing an existing user's email address returns the right record. Applying first item to that result turns the list into a single thing.
Turning a single record into a list
Sometimes you'll need to go the other way, turning a single item into a list, even if that list holds only the one record. To do this, use the converted to list operator.
This comes up whenever something in your app expects a list but what you have is a single thing.
Converting a single record into a list examples
Converting a single record into a list examples
Passing it to an action that expects a list. Some workflow actions (such as Copy a list of things) take a list of things. If you only have a single record but the action needs a list, converting it lets you pass it through.
Setting a list field on another thing. A field that stores a list of things expects a list value. To save a single record into it, convert it first.
Passing a single record to a backend workflow that takes a list. If a backend workflow's parameter is defined as a list of things, a single record needs converting before you can send it.
Other data sources
Searching with Do a search for is one way to find data, but not the only one. Depending on what you need, another data source may get you there more directly.
Data source | Description | Returns |
Do a search for | Searches the database using constraints. | A list of things |
Current user | The user currently using the app. | One thing |
Current page thing | The record currently loaded onto the page with the Go to page action. | One thing |
Get data from page URL | A thing retrieved from a URL parameter that contains a unique ID. | One thing |
Thing's X | A value stored in a field on another thing, such as Current User's Company. | A list or a single item, depending on the field |
Other ways to learn
Core reference
Core reference
Notes
A data source is the part of an expression that defines where Bubble pulls the data from.
In this context, the data source is a database search.
A conditional expression is a way to ask Bubble a question that returns either true or false.
You can then use the answer in some kind of logic, such as changing an element's formatting or deciding whether a workflow should run.
Container elements such as a group can have a database thing loaded into them.
This lets each child element reference that data to display content, auto-bind input elements, and use it in workflows.
Article: The element hierarchy Article section: Loading data into containers
Elements are all the things you place on the page, such as containers, input forms, and visual elements like icons and images.
Article series: Elements
An operator is any step you add to an expression after the data source.
For example, if you have a list of things and you want to return the first item in that list, the expression might look like this:
Do a search for:first item. Here, theDo a search foris the data source andfirst itemis the operator.The issue tracker is the counter in the upper-right part of the Bubble editor. Whenever there's one or more issue with your app, it shows red text and the number of issues.
Pseudorandomness means the generated number appears random but is actually produced by a deterministic system.
To your users it makes no noticeable difference, but it means the number isn't cryptographically secure.




