# Search Threads with logical OR

**URL:** <https://forums.nylas.com/t/search-threads-with-logical-or/421>\
**Category:** Question and Answers\
**Created:** [September 6, 2024, 8:27am UTC](https://forums.nylas.com/t/search-threads-with-logical-or/421 "2024-09-06T08:27:23Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![gpapidas](https://avatars.discourse-cdn.com/v4/letter/g/c37758/32.png) [@gpapidas](https://forums.nylas.com/u/gpapidas)\
**Post date:** [September 6, 2024, 8:27am UTC](https://forums.nylas.com/t/search-threads-with-logical-or/421/1 "2024-09-06T08:27:23Z")

</div>

Hello everyone!

I would like to filter threads using a search as described here: [Nylas v3 Email, Calendar, and Contacts API docs | Nylas Docs](https://developer.nylas.com/docs/api/v3/ecc/#tag--Threads--search-threads)

My use case is that a user will type their search string and this will be used to find the threads that either contain this in their subject or there is an email associated with that search string in the thread. After that the threads shall be returned from last to first.

I see I can use the columns “subject” and “any\_email” which would serve my purpose quite well but there is not an option for a logical OR between the two. I can see that the ordering is by default that the latest thread should come first so in that aspect everything is ok.

I could see one solution being that I could make 2 separate requests in the same API, one with “subject” and another with “any\_email” but there is an issue there in both ordering of the eventual response data and pagination.

Another solution I have considered for this is to use `search_query_native` and do something like the following: (I am using Microsoft provider)

filter\_query = (  
f"$filter=contains(subject,‘{search\_string}’) or "  
f"contains(from/emailAddress/address,‘{search\_string}’)"  
)

The problem with the above solution however is that results do not come ordered by latest date, and I can not seem to find a way to order them.

Any ideas?

Thanks a lot in advance 🙂

---

<div class="post-metadata">

**Author:** ![Blag](https://sea1.discourse-cdn.com/flex015/user_avatar/forums.nylas.com/blag/32/9_2.png) [@Blag](https://forums.nylas.com/u/Blag)\
**Post date:** [September 6, 2024, 11:05am UTC](https://forums.nylas.com/t/search-threads-with-logical-or/421/2 "2024-09-06T11:05:56Z")

</div>

Hello @gpapidas why don’t put the results in an array, make the date a date type and then sort the array the way you need it…I would do it that way 🤔

---

<div class="post-metadata">

**Author:** ![gpapidas](https://avatars.discourse-cdn.com/v4/letter/g/c37758/32.png) [@gpapidas](https://forums.nylas.com/u/gpapidas)\
**Post date:** [September 6, 2024, 12:08pm UTC](https://forums.nylas.com/t/search-threads-with-logical-or/421/3 "2024-09-06T12:08:21Z")

</div>

That would unfortunately not work quite well. Here’s an example.

If we assume we are making 2 separate requests, one with subject and one with any email then we will get 2 separate responses.

Let’s assume that from the subject request the response is the following.

data = [{“value”: 1, “date”: Sep 5th}, {“value”: 2, “date”: Sep 4th}, {“value”: 3, “date”: Sep 3rd}] and then we have a page\_token to go to page 2, where we would have values 4, 5 and 6 with dates Sep 2, Sep 1, August 31 respectively.

Now let’s say that in a similar manner my request with the “any\_email” parameter has the following response.

page 1: data = [{“value”: 10, “date”: Sep 4th}, {“value”: 20, “date”: Sep 4th}, {“value”: 30, “date”: Sep 3rd}] and  
page 2: data = [{“value”: 30, “date”: Sep 3rd}, {“value”: 40, “date”: Sep 2nd}, {“value”: 50, “date”: Sep 1st}]

now, if we combine the results of the first page and we want to serve 3 elements per page, we will serve, according to dates the following.

data = [{“value”: 1, “date”: Sep 5th}, {“value”: 2, “date”: Sep 4th}, {“value”: 10, “date”: Sep 4th}]

and that would probably work fine.

But what happens when the user wants to go to the second page?  
How could I get the next correct set of data which would be the following

data = [{“value”: 20, “date”: Sep 4th}, {“value”: 3, “date”: Sep 3rd}, {“value”: 30, “date”: Sep 3rd}]

I mean, I could probably do something custom, but all the solutions I have thought involve creating a somewhat complex solution by keeping correct order from Nylas multiple API requests while also solving a problem of keeping 2 next\_cursor values.

That’s why ideally I’d like to avoid this if possible.

---

<div class="post-metadata">

**Author:** ![davidpal](https://avatars.discourse-cdn.com/v4/letter/d/7bcc69/32.png) [@davidpal](https://forums.nylas.com/u/davidpal)\
**Post date:** [January 20, 2026, 5:59pm UTC](https://forums.nylas.com/t/search-threads-with-logical-or/421/4 "2026-01-20T17:59:12Z")

</div>

Did you ever solve this?

---

<div class="post-metadata">

**Author:** ![gpapidas](https://avatars.discourse-cdn.com/v4/letter/g/c37758/32.png) [@gpapidas](https://forums.nylas.com/u/gpapidas)\
**Post date:** [January 20, 2026, 6:28pm UTC](https://forums.nylas.com/t/search-threads-with-logical-or/421/5 "2026-01-20T18:28:04Z")

</div>

Hey, I ended up storing the threads/emails into my own database and creating a custom search using tsvector/embeddings. If you follow this path, there is a rate limiting you’ll have to take into account if you try to sync historical emails of your users to your database.

I have not searched the documentation recently, but then there was no information about what this rate limiting is unfortunately. I had a call with Nylas support back then and they told me that it was 1 request every minute, but this is not true. I don’t remember the exact requests/minute I ended up doing, but you will need to experiment.

Generally, depending on what you are trying to build, you will find yourself wanting to store the threads/emails into your own database for a lot of cases.

Hope I helped even a little 🙂

---

<div class="post-metadata">

**Author:** ![Samuel.R](https://avatars.discourse-cdn.com/v4/letter/s/6bbea6/32.png) [@Samuel.R](https://forums.nylas.com/u/Samuel.R)\
**Post date:** [January 20, 2026, 6:37pm UTC](https://forums.nylas.com/t/search-threads-with-logical-or/421/6 "2026-01-20T18:37:14Z")

</div>

Hello,

The standard Nylas query parameters combine **`subject`** and **`any_email`** with AND logic, not OR. After digging into this, here’s what I found and the recommended solution.

For Microsoft provider, you can use **`search_query_native`** with native **`$search`** query syntax that supports OR:

```python
import urllib.parse

search_string = "test"
search_query = f"subject:{search_string} OR from:{search_string} OR to:{search_string} OR cc:{search_string} OR bcc:{search_string}"
encoded_query = urllib.parse.quote(search_query)

# GET /v3/grants/{grant_id}/threads?search_query_native={encoded_query}

```

Regarding the ordering challenge, this is actually a **Microsoft Graph API limitation** , not a Nylas limitation. When using **`$search`** , Microsoft Graph returns results by “relevance” and doesn’t support combining it with **`$orderby`**. This is why your **`$filter`** approach with **`contains()`** also doesn’t work with ordering.

Since server-side ordering isn’t available with $search, here’s a practical pattern:

```python
import urllib.parseimport requests

def search_threads_with_or(grant_id, search_string, api_key, page_size=50):# Build OR query for subject and email participants

search_query = (f"subject:{search_string} OR "f"from:{search_string} OR "f"to:{search_string} OR "f"cc:{search_string} OR "f"bcc:{search_string}")

encoded_query = urllib.parse.quote(search_query)

response = requests.get(
    f"https://api.us.nylas.com/v3/grants/{grant_id}/threads",
    params={
        "search_query_native": encoded_query,
        "limit": page_size
    },
    headers={"Authorization": f"Bearer {api_key}"}
)

data = response.json()
threads = data.get("data", [])
next_cursor = data.get("next_cursor")

# Sort by latest message date (client-side)
sorted_threads = sorted(
    threads,
    key=lambda t: t.get("latest_message_timestamp", 0),
    reverse=True
)

return sorted_threads, next_cursor

```

For pagination with proper ordering, you have two options:

**Option 1: Fetch-and-Sort (Simpler)**

- Fetch larger batches (50-100 threads)

- Sort client-side by **`latest_message_timestamp`**

- Present smaller virtual pages to users

- Use Nylas **`next_cursor`** to fetch more batches as needed

**Option 2: Two-Request Merge (More Complex)**

If you need precise pagination:

1. Make parallel requests with **`subject`** and **`any_email`** separately

2. Deduplicate by thread ID

3. Sort the merged results

4. Track both pagination cursors and implement virtual pagination

Option 1 is usually sufficient for most use cases and much simpler to implement.

**Important Note**

When using **`search_query_native`** with Microsoft provider, you can only combine it with **`in`** , **`limit`** , and **`page_token`** parameters no other filters are allowed.

Hope this helps! Let me know if you have questions about the implementation.

Many thanks,  
Samuel R.  
Support Engineer, Nylas
