When making a query via the REST API, you don't have the luxury of binding a collection with :
to help avoid character limits on the WHERE
clause, or the entire query.
Instead, your client code, wherever it lives and whatever language it's written in, must take responsibility for tracking the length of the generated query, which will include the literal values of whatever strings you are filtering against in your IN
clause.
I've written code that does this for Ids
in Python, which I previously discussed on SFSE here. In pseudo-Python, the algorithm looks like this:
query = 'SELECT Id, Name, Email, Account.Id, Account.Name FROM Contact {}'
where_clause = 'WHERE Email in ({})'
where_clause_length = len(where_clause) - 2 # 2 characters are the merge field {}
email_addresses = [] # put your email addresses in a collection.
# Iterate and make queries until we run out of email addresses
# n.b. there's surely a more elegant way to do this, but it works.
while len(email_addresses) > 0:
# Start building a query.
this_batch = '\'' + email_addresses.pop() + '\''
# The maximum length of the WHERE clause is 4,000 characters
# Iterate while (a) we have more emails and (b) we have space in this query.
while len(email_addresses) > 0:
# Make sure we have space for the next item.
# We should escape or clean single quotes in the email address, which would add a bit of complexity.
if where_clause_length + len(this_batch) + len(email_addresses[-1:]) + 3 < 4000:
query += ',\'' + email_addresses.pop() + '\''
else:
break
# Now run this query and iterate again.
results = sf.query_all(query.format(where_clause.format(this_batch)))
for res in results.get('records'):
self.add_result(res)
SOSL
Whether to use SOSL is going to depend on your exact requirements. While SOSL can search multiple objects in a single operation, the semantics of a SOSL search are different than SOQL and subject to different limits. If your goal is to identify every single record containing these emails, SOSL is not a fit for you:
The search engine looks for matches to the search term across a maximum of 2,000 records (this limit starts with API version 28.0)
SOSL applies different limits for a given object or situation. If the search is for a single object, the full record limit is applied. If the search is global across multiple objects, each object has individual limits that total 2,000 records.
Instead, you'd just run SOQL queries across more than one object and aggregate your results in your client code.
If the SearchQuery string is longer than 10,000 characters, no result rows are returned. If SearchQuery is longer than 4,000 characters, any logical operators are removed. For example, the AND operator in a statement with a SearchQuery that’s 4,001 characters will default to the OR operator, which could return more results than expected.