|
3. Querying
3.5 Query by Example
A new feature introduced in ReStore 1.20 is an alternative method of querying - Query by Example. This is a powerful new way of querying, which can be used in addition to the block-based methods (e.g. select: and satisfying:) discussed so far.
Querying by example is accomplished by creating a template object which is 'similar to' the instance(s) you wish to find in the database. By 'similar to', we mean that the template object has certain of its instance variables filled, and 'similar' instances will have the same instance variables filled with the same values.
Once a template object has been created, sending it the message similarInstancesIn: will result in an instancesOf: collection of matching objects from the database. This collection can then be used in the same ways discussed earlier (e.g. asOrderedCollection to return an actual Smalltalk collection, satisfying: to further refine etc.). Example:
template := Person new.
template surname: 'Smith'.
allSmiths := template similarInstancesIn: aReStore.template address city: 'London'.
allSmithsInLondon := template similarInstancesIn: aReStore.Query by example is particularly useful when developing a 'Find'-type screen. The model of the screen would be the template object; as the user fills in the details to be found, the template object is also filled in. When the user hits 'Find', it is only necessary to send similarInstancesIn: to the template object to find the required instances.
Wildcards
One potential disadvantage with the use of template objects is that they require a 'hard' match - e.g. in the above example, someone named 'Smithe' would not be included in the resulting collection, which may not be what was required.In a block-based query, it is possible to use the match: message to look for a partial match such as this (e.g. 'Smith*' match: surname). To check for such partial matches when querying by example, it is necessary to send the message asWildcard to the String denoting a partial match, e.g.
template := Person new.
template surname: 'Smith*' asWildcard.
allSmithsSmithesEtc := template similarInstancesIn: aReStore.
The EntertainmentShop example application demonstrates the use of Query by Example with wildcards in the class FindCustomerShell.
Use of nil
Querying by example relies on only the aspects of interest being set in the template object - any attribute which is unset will be nil, and is thus ignored when determining the similar instances.Occasionally however it can be useful for an unset attribute to be a requirement of the similar objects. For example, to determine any unsent Order objects, it may be necessary to check for Orders with a despatchDate of nil. Such a requirement can be expressed by sending the message required to nil:
template := Order new.
template despatchDate: nil required.
allUnsentOrders := template similarInstancesIn: aReStore.
3.5 Query by Example