[Glass] There is really no way to have an ordered/sorted collection together with indexes?

Mariano Martinez Peck via Glass glass at lists.gemtalksystems.com
Mon Aug 7 19:53:11 PDT 2017

On Mon, Aug 7, 2017 at 10:47 PM, Dale Henrichs via Glass <
glass at lists.gemtalksystems.com> wrote:

> On 8/7/17 1:04 PM, Richard Sargent via Glass wrote:
>> GLASS mailing list wrote
>>> Hi guys,
>>> I am storing huge lists of "prices". For this, it really helps me to
>>> store
>>> things ordered (by date)...either in an SequenceableCollection or a
>>> SortedCollection. On the other hand, I do want to use indexes to speedup
>>> my
>>> query to find price for a given date (equality index).
>>> But I have found no way to have them both. The only workaround I found is
>>> to keep 2 collections for each of these collections, one sorted/ordered,
>>> and the other one an unordered one for querying via index. But this is a
>>> pain from "developing" point of view, as well as for unnecessary
>>> repository
>>> growth.
>>> Am I missing something?
>> Mariano, have you read chapter 7 in the GemStone/S 64 Programming Guide?
>> It's all about indexing.
>> It looks like you could define a "range" query over the unordered
>> collection
>> to get the sorted sequence needed to traverse all the prices in date
>> order.
>> The index would be on the date and the range query would be from some
>> "least
>> date" through some "greatest date". You would then use the streaming
>> results
>> or the #do: message I think) to iterate over the query result in date
>> order.
>> There is a section in chapter 7.2 discussing result order.
>> It might be helpful to discuss the use cases for the two collections. When
>> would you iterate over all the dates versus when would you search for
>> specific dates or ranges of dates?
>> Actually I think you can just set up two queries ... one to search for
> the exact date:
>   detectQuery := (GsQuery fromString: 'each.value = targetDate' on: nsc)
> and one query to find the first date prior to your targetDate:
>   nearestQuery := (GsQuery fromString: 'each.value < targetDate' on: nsc)

Hi Dale,

Thanks for your answers. I am headed bed right now, but I would do a quick
question so to have as much as possible info for tomorrow...

Aside from both needed queries above, I would still need this 2 more APIs:

3) get the whole price history sorted.
4) get the newest available price of the collection

How can I make those fast too taking advantage of the index? For 3) I can
simply do the nearestQuery with a future day (like tomorrow), but maybe
there is a cleaner way?  And for 4?

In summary.... I am comparing whether store things sorted (so that 3 and 4
are fast...3 is a simple #last and 4 is simple same collection..nothing to
do ) and make binary search for exact query and nearest query, vs  store
things in a bag and do everything via index (querying will be fast, but I
doubt about 3) and 4)... i mostly doubt about 3)..

Thanks a lot!

> Then you can use detect:ifNone: sent to the query object itself to either
> find the first matching date using the index or the first date prior to the
> target data using an index ... in both queries you are using very efficient
> btree lookups and avoiding the need to scan your collection (key is the
> price and value if the date):
>       | nsc random maxYear detectQuery targetDate result |
>       nsc := IdentityBag new.
>       random := HostRandom new.
>       GsIndexSpec new
>         equalityIndex: 'value' lastElementClass: Date;
>         createIndexesOn: nsc.
>       1 to: 100 do: [ :index |
>         nsc
>           add: (ScaledDecimal for: random float scale: 2) ->
>             (Date
>               newDay: (random integerBetween: 1 and: 365)
>               year: (random integerBetween: 2000 and: 2017)) ].
>       targetDate := Date newDay: 250 year: 2011.
>       detectQuery := (GsQuery fromString: 'each.value = targetDate' on:
> nsc)
>         bind: 'targetDate'
>         to: targetDate.
>       result := detectQuery
>         detect: [ :date | true ]
>         ifNone: [ | nearestQuery |
>           nearestQuery :=  (GsQuery fromString: 'each.value < targetDate'
> on: nsc)
>             bind: 'targetDate'
>             to: targetDate.
>            nearestQuery reversedReadStream next].
>       {nsc. nsc sortAscending: 'value'. targetDate. result}
> I'm returning the sorted nsc, to make it easy to validate that  the result
> is correct, since we're generating random dates.
> The parsed query can be persisted (with or without the nsc attached) to
> avoid the overhead of parsing the query string each time you run the query
> ...
> _______________________________________________
> Glass mailing list
> Glass at lists.gemtalksystems.com
> http://lists.gemtalksystems.com/mailman/listinfo/glass

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.gemtalksystems.com/mailman/private/glass/attachments/20170807/757932e6/attachment-0001.html>

More information about the Glass mailing list