realm-js icon indicating copy to clipboard operation
realm-js copied to clipboard

Realm query objects by array of ids

Open pollend opened this issue 4 years ago • 9 comments

Questions: I want to query by a list of ids but I get this error when I try to query by this:

byIds(ids: string[]) {
    return   this._realm
        .objects(Provider)
        .filtered('id IN $0',ids)
  }

The expression following 'IN' must be a keypath to a list

image

Version of Realm and Tooling

  • Realm JS SDK Version: 4.0.0-beta.0
  • Node or React Native: 0.61.5
  • Client OS & Version: Android
  • Which debugger for React Native: None

pollend avatar Mar 31 '20 16:03 pollend

Hey @pollend Realm JS currently does not support IN statement. We do this in our project by joining array with OR like:

const idsQuery = [1,2,3,4].map(id => `userId = ${id}`).join(' OR ');
realm.objects().filtered(`(${idsQuery})`)

bimusiek avatar Apr 01 '20 12:04 bimusiek

that's nice to know. I saw some sample code floating around that uses the IN statement. will there be support for this in the future? seems like the query might become quite expensive if you have a large number of id's.

pollend avatar Apr 01 '20 18:04 pollend

You need answer from Realm team. 😅

I based my answer on https://github.com/realm/realm-js/issues/450

bimusiek avatar Apr 01 '20 19:04 bimusiek

We would like to implement full support for "IN" at some point, but because of the workaround mentioned here with chaining equality with "OR" it hasn't been a high priority. We do have an optimization at a lower level which combines these types of "equal OR equal" chains together, so even though you are writing out the query in long form, the execution should still be quite fast.

ironage avatar Apr 01 '20 21:04 ironage

realm.objects().filtered(`(${idsQuery})`)

Can we do it on object ids?

abhishekmatta999 avatar Apr 23 '21 11:04 abhishekmatta999

@abhishekmatta999 yes, the workaround works on any type of value. If you are having issues with your query, let us know more details so we can try to help you.

ironage avatar Apr 23 '21 17:04 ironage

@ironage Hi, Im getting this error when I'm trying it with object-ids

Invalid predicate: '(_id = 606b439ede7a330008506642 OR _id = 606b43a17375130009ef5864 OR _id = 606b43814e9a5900086fc20b OR _id = 606b438a3237c60008596144)': syntax error, unexpected identifier, expecting || or ')'

My query is: let filteredQuery = publicationIds.map(id => _id = ${id}).join(' OR '); let result = await publicRealm.objects('catalogpublication').filtered((${filteredQuery}))

abhishekmatta999 avatar Apr 23 '21 18:04 abhishekmatta999

@abhishekmatta999 the best practice is to pass your variables in by argument substitution, then you don't have to worry about the format. With the object id's stored in variables oid1 and oid2 the pattern looks like this: realm.objects().filtered("_id = $0 OR _id = $1", oid1, oid2)

If you really need to hard code the object id's into the query string then they should be formatted into "oid(...)" like this: realm.objects().filtered("_id = oid(606b439ede7a330008506642) OR _id = oid(606b43a17375130009ef5864)")

ironage avatar Apr 23 '21 21:04 ironage

Hi,

Any update for 2022 usecases, IN operator is supported NOW!!

We need to filter object like this:

realm.objects('Car').filtered('id IN [1, 2, 3]');

Thanks!

dridi93 avatar May 20 '22 15:05 dridi93

Next release (v10.20.0) will include an enhancement of the IN to support what os requested here.

kneth avatar Aug 23 '22 07:08 kneth

Next release (v10.20.0) will include an enhancement of the IN to support what os requested here.

Hi @kneth,

First of All, thanks for this realease,

I have a question plz, what about 'NOT IN', how can i achieve this case ?

UPDATE

I use NOT id IN {1,2,3,4}, and it's work!!!

dridi93 avatar Aug 25 '22 09:08 dridi93

@dridi93 You can use NONE, ANY and ALL with IN.

We haven't got around documenting it yet, but you can take a look at one of our tests: https://github.com/realm/realm-js/blob/master/integration-tests/tests/src/tests/queries.ts#L76-L88

kneth avatar Aug 25 '22 16:08 kneth

I am using v11.0.0-rc.1 and have seen errors when trying to use IN with a non-object list, I tried several query arguments and all resulted in the same error as #4596

class MyObject extends Realm.Object {
  static schema = {
    name: 'MyObject',
    properties: {
      Id: 'string',
    }
  }
}

// idList = ['id1', 'id2']
realm.objects(MyObject).filtered('Id IN $0', idList);

// idList = "['id1','id2']"
realm.objects(MyObject).filtered('Id IN $0', idList);

// idList = "{'id1', 'id2'}"
realm.objects(MyObject).filtered('Id IN $0', idList);

My current workaround is to just use filter() and run the logic myself, which is good enough but obviously I'd like to use the DB level query if possible.

realm.objects(MyObject).filter(o => idList.includes(o.Id));

tehvgg avatar Oct 21 '22 17:10 tehvgg

Hi @tehvgg, the earliest release in the 11 series to include "IN" query support is v11.0.0-rc.2. We have been publishing release candidates for v11 in parallel with stable v10 development which produces the somewhat surprising effect that updating to a higher major version does not necessarily include a feature released in a lower major version. That said, we recently released v11.0.0 which I'd recommend updating to over the previous rc versions if you are able to adapt to the breaking changes.

ironage avatar Oct 21 '22 18:10 ironage

@ironage I thought that might be the case, initially I couldn't upgrade past rc.1 as my environment is a bare expo (SDK 46) workflow tied to RN 0.69, but I'll try the new stable v11 if it's compatible with my environment.

Thanks!

EDIT: v11 is 0.70+ so I'll be waiting for Expo 47 :)

tehvgg avatar Oct 21 '22 18:10 tehvgg

For me using realm 11.3.1 & realm/react 0.4.3 , I was not able to query the way I was thinking it would work... Its not accepting string array as parameter

participantsProfileIds - ['key1', 'key2']

realm.objects('User').filtered(`externalId IN $0`, participantsProfileIds)

Instead had to use the following workaround:

realm.objects('User').filtered(`externalId IN { ${participantsProfileIds.map(x => `'${x}'`).join(', ')} }`)

Not sure which is better, this one above or the ' OR ' solution... seems like both are nasty hacks

geo-vi avatar Mar 27 '23 17:03 geo-vi

@geo-vi what is the error that you are getting when passing an array of strings as an argument for the $0 syntax? I would expect that to be working.

Not sure which is better, this one above or the ' OR ' solution...

It is more efficient to use the x IN {...} syntax over the chained OR solution.

ironage avatar Mar 27 '23 17:03 ironage

@ironage

@geo-vi what is the error that you are getting when passing an array of strings as an argument for the $0 syntax? I would expect that to be working.

no error however, I am not getting results either.

the arg that I am passing is a simple string array - ['key1', 'key2']

geo-vi avatar Mar 27 '23 18:03 geo-vi

@geo-vi could you open a new bug report in this repository? It would be very helpful to include the exact string array argument and query in a minimal reproduction case if you are able to make one that doesn't include user data.

ironage avatar Mar 27 '23 19:03 ironage

Finally i found a way for it to query by multiple object ids in react native.

const idsQuery = selectedItemIds.map(id => `oid(${id})`).join(', ');

const selectedItems = items.filtered(`_id IN { ${idsQuery} }`);

hardik-javascript avatar May 16 '23 06:05 hardik-javascript