realm / realm-core

Core database component for the Realm Mobile Database SDKs
https://realm.io
Apache License 2.0
1.01k stars 155 forks source link

Bitwise operators for querying #1419

Open kneth opened 8 years ago

kneth commented 8 years ago

Motivated by https://github.com/realm/realm-java/issues/1949.

It is useful to be able to query integer columns using bitwise operators. Of course, it is easy to split easy bit into separate boolean columns but we might give our users the freedom to choose.

jpsim commented 8 years ago

Cocoa issue: https://github.com/realm/realm-cocoa/issues/1229

danpe commented 7 years ago

👍

gcox commented 6 years ago

I'd love to take a stab at this since since no one else seems to be looking into it...seems like I'd have plenty of time to figure it out 🤓.

That said, the wording of the opening comment makes it sound like it may or may not be accepted, regardless of the quality of the implementation. Just don't want to waste my time. Can someone confirm whether this is an approved feature to work on?

astigsen commented 6 years ago

Can you give an example of what the use case would be? In most cases it should be a lot more efficient with a number of boolean columns as the storage engine can do all kinds of optimizations on those. In most cases they will both take up less space internally and be much faster to query on.

But if there is a good use case for storing them as ints which is not covered by boolean sets (maybe if you also need the full value?) we should definitely support it.

Any specific use cases you have in mind?

gcox commented 6 years ago

Yes, my own app (currently uses Core Data, converting to Realm). It is a podcast player that supports 'smart' playlists. It supports including episodes in a playlist based on a list of criteria that will only grow. The screenshot below is of the actual list of criteria in the settings view for a playlist, which requires some explanation...

Playlist Criteria

The resulting logic from the configuration shown in the screenshot reads like this:

(partiallyPlayed) 
&& !(played || video || non-local)
&& (unplayed || audio || downloaded || streamed || downloading || locked) 

I originally represented these attributes of an episode as a bunch of boolean properties but once this became too frustrating to deal with, I rolled them into a single flag property, which has been far more pleasant to work with. Now, an episode has a single attributeFlags property. The playlist object was modified to roll it's filter options into three properties:

The original query was a series of boolean checks, as has already been suggested as the alternative to bitwise comparison. It was a pain to deal with, had to be generated, required a change every time a new characteristic was added, and, of course, adding a new characteristic meant a new/altered index.

The new query looks something like this, requires no code to generate, never has to be altered, and I don't have to remember to add/update indexes.

(flags & requiredFlags) == requiredFlags 
AND (flags & exclusionFlags) == 0
AND (flags & inclusionFlags) > 0

In my particular case, this has had little to no performance impact, and a very positive impact on maintenance (and my mood when I get near it).

Sorry for the length of all that, but I wanted to be as clear as possible.