Multi-indexes allow to easily create complex indexes.
Here is a excerpt of doc/contrib.rst about the creation of the DateTimeIndex:
DateTimeIndex
The limpyd.contrib.indexes module provides a DateTimeIndex (and other
friends). In this section we'll explain how it is constructed using only
the configure method of the normal indexes, and the compose method of
MultiIndexes
Goal
We'll store date+times in the format YYYY-MM-SS HH:MM:SS.
We want to be able to:
filter on an exact date+time
filter on ranges on the date+time
filter on dates
filter on times
filter on dates parts (year, month, day)
filter on times parts (hour, minute, second)
Date and time parts
Let's separate the date, and the time into YYYY-MM-SS and HH:MM:SS.
How to filter only on the year of a date: we want to extract the 4 first
characters, and filter it as number, using NumberRangeIndex:
Also, we don't want uniqueness on this index, and we want to prefix the
part to be able to filter with myfield__year=2015
If we want to filter not only on parts but also on the full date with a
TextRangeIndex, to be able to do date_field__gte=2015, we'll need
another index.
We don't want to use a prefix, but if we have another TextRangeIndex on
the field, we need a key:
We don't keep theses two indexes apart from the DateIndexParts and
TimeIndexParts because we'll need them independently later to prefix
them when used together.
Full indexes
But if we want full indexes for dates and times, including the range
and the parts, we can easily compose them:
Now that we have all that is needed for fields that manage date OR time,
we'll combine them. three things to take in consideration:
we'll have two TextRangeIndex, one for date one for time. So we need
to explicitly prefix the filter, to be able to do datetime_field__date__gte='2015' and
datetime_field__time__gte='15:'
we'll have to extract the date and time separately
we'll need a TextRangeIndex to filter on the whole datetime to be
able do to datetime_field__gte='2015-12-21 15:'
In the first time, we'll want an index without the time parts, to allow
filtering and the three "ranges" (full, date, and time), but only on
date parts, not time parts. It can be useful if you know you won't have
to search on this.
So, to summarize, we need:
a TextRangeIndex for the full datetime
the DateRangeIndex, prefixed
the DateIndexParts
the TimeRangeIndex, prefixed
Which gives us:
>>> DateSimpleTimeIndex = MultiIndexes.compose([
... TextRangeIndex.configure(key='full', name='FullDateTimeRangeIndex'),
... DateRangeIndex.configure(prefix='date'),
... DateIndexParts,
... TimeRangeIndex.configure(prefix='time', transform=lambda value: value[11:]) # pass only time
... ], name='DateSimpleTimeIndex', transform=lambda value: value[:19]) # restrict on date+time
And to have the same with the time parts, simply compose a new index
with the last one and the TimeIndexPart:
>>> DateTimeIndex = MultiIndexes.compose([
... DateSimpleTimeIndex,
... TimeIndexParts.configure(transform=lambda value: value[11:]), # pass only time
... ], name='DateTimeIndex')
This PR depends on #101
Multi-indexes allow to easily create complex indexes.
Here is a excerpt of
doc/contrib.rst
about the creation of theDateTimeIndex
:DateTimeIndex
The
limpyd.contrib.indexes
module provides aDateTimeIndex
(and other friends). In this section we'll explain how it is constructed using only the configure method of the normal indexes, and the compose method ofMultiIndexes
Goal
We'll store date+times in the format
YYYY-MM-SS HH:MM:SS
.We want to be able to:
Date and time parts
Let's separate the date, and the time into
YYYY-MM-SS
andHH:MM:SS
.How to filter only on the year of a date: we want to extract the 4 first characters, and filter it as number, using
NumberRangeIndex
:Also, we don't want uniqueness on this index, and we want to prefix the part to be able to filter with
myfield__year=2015
So this part could be:
Doing the same for the month and day, and composing a multi-indexes with the three, we have:
If we do the same for the time only (assuming a time field without date), we have:
Range indexes
If we want to filter not only on parts but also on the full date with a
TextRangeIndex
, to be able to dodate_field__gte=2015
, we'll need another index.We don't want to use a prefix, but if we have another
TextRangeIndex
on the field, we need a key:The same for the time:
We don't keep theses two indexes apart from the
DateIndexParts
andTimeIndexParts
because we'll need them independently later to prefix them when used together.Full indexes
But if we want full indexes for dates and times, including the range and the parts, we can easily compose them:
Now that we have all that is needed for fields that manage date OR time, we'll combine them. three things to take in consideration:
TextRangeIndex
, one for date one for time. So we need to explicitly prefix the filter, to be able to dodatetime_field__date__gte='2015'
anddatetime_field__time__gte='15:'
TextRangeIndex
to filter on the whole datetime to be able do todatetime_field__gte='2015-12-21 15:'
In the first time, we'll want an index without the time parts, to allow filtering and the three "ranges" (full, date, and time), but only on date parts, not time parts. It can be useful if you know you won't have to search on this.
So, to summarize, we need:
TextRangeIndex
for the full datetimeDateRangeIndex
, prefixedDateIndexParts
TimeRangeIndex
, prefixedWhich gives us:
And to have the same with the time parts, simply compose a new index with the last one and the
TimeIndexPart
:And we're done !