
When indexing message attachment metadata using numeric indexes such as: ```javascript { conversationId: '+12223334455', received_at: 123, attachments: […], numAttachments: 2, }, { conversationId: '+12223334455', received_at: 456, attachments: [], numAttachments: 0, } { conversationId: '+12223334455', received_at: 789, attachments: [], numAttachments: 1, } ``` It creates an index as follows: ``` [conversationId, received_at, numAttachments] ['+12223334455', 123, 2] ['+12223334455', 456, 0] ['+12223334455', 789, 1] ``` This means a query such as… ``` lowerBound: ['+12223334455', 0, 1 ] upperBound: ['+12223334455', Number.MAX_VALUE, Number.MAX_VALUE] ``` …will return all three original entries because they span the `received_at` from `0` through `Number.MAX_VALUE`. One workaround is to index booleans using `1 | undefined` where `1` is included in the index and `undefined` is not, but that way we lose the ability to query for the `false` value. Instead, we flip adjust the index to `[conversationId, hasAttachments, received_at]` and can then query messages with attachments using ``` [conversationId, 1 /* hasAttachments */, 0 /* received_at */] [conversationId, 1 /* hasAttachments */, Number.MAX_VALUE /* received_at */] ```
13 lines
393 B
TypeScript
13 lines
393 B
TypeScript
/**
|
||
* @prettier
|
||
*/
|
||
|
||
// IndexedDB doesn’t support boolean indexes so we map `true` to 1 and `false`
|
||
// to `0`.
|
||
// N.B. Using `undefined` allows excluding an entry from an index. Useful
|
||
// when index size is a consideration or one only needs to query for `true`.
|
||
export type IndexableBoolean = 1 | 0;
|
||
|
||
export const toIndexableBoolean = (value: boolean): IndexableBoolean =>
|
||
value ? 1 : 0;
|