( source: MaybeObservableArray<Entity<Data, View>>, store: EntityStore<Data, View>, queryObject: FindObjectInput<Data & View> )
| 47 | } |
| 48 | |
| 49 | export function findInSourceByObjectInput<Data, View>( |
| 50 | source: MaybeObservableArray<Entity<Data, View>>, |
| 51 | store: EntityStore<Data, View>, |
| 52 | queryObject: FindObjectInput<Data & View> |
| 53 | ) { |
| 54 | if (source.length === 0) return []; |
| 55 | |
| 56 | const { $or, ...requiredKeysRaw } = queryObject; |
| 57 | |
| 58 | const itemsMatchingRootQuery = getRemainingItemsAfterApplyingQueryFields( |
| 59 | source, |
| 60 | store, |
| 61 | requiredKeysRaw as FindObjectPartInput<Data & View> |
| 62 | ); |
| 63 | |
| 64 | if (!itemsMatchingRootQuery.length) { |
| 65 | return []; |
| 66 | } |
| 67 | |
| 68 | if (!$or) { |
| 69 | return itemsMatchingRootQuery; |
| 70 | } |
| 71 | |
| 72 | if (!$or.length) { |
| 73 | return itemsMatchingRootQuery; |
| 74 | } |
| 75 | |
| 76 | const orQueriesResults = $or.map((orQuery) => { |
| 77 | return getRemainingItemsAfterApplyingQueryFields(source, store, orQuery); |
| 78 | }); |
| 79 | |
| 80 | const maxOrResultSize = getMaxBy(orQueriesResults, (result) => result.length); |
| 81 | |
| 82 | /** |
| 83 | * Performance optimization. eg. if itemsMatchingRootQuery has 3 items, but or results have 1000 - it would be big bottleneck to first create unique array out of it |
| 84 | * Instead, we'll be able to quickly iterate with small array of root query items over every or query |
| 85 | */ |
| 86 | if (maxOrResultSize > itemsMatchingRootQuery.length) { |
| 87 | return getArraysCommonPart(itemsMatchingRootQuery, ...orQueriesResults); |
| 88 | } |
| 89 | |
| 90 | // Root is matching more items than or queries - we'll create unique list of or queries and compare then. |
| 91 | return getArraysCommonPart( |
| 92 | uniq(orQueriesResults.flat()), |
| 93 | itemsMatchingRootQuery |
| 94 | ); |
| 95 | } |
| 96 | |
| 97 | type FindFunctionalInput<T> = (item: T) => boolean; |
| 98 |
no test coverage detected