К операциям с древовидными индексами относятся операции, использующие деревья с
индексами и реализующие над ними теоретико - множественные операции. К таким
операциям
относят логические операции над множествами: OR (ИЛИ), AND (И), и другие. При
этом деревья используются для хранения множеств - операндов и результата
операции.
Структурно древовидный индекс удерживает как значения атрибутов, так и идентификаторы записей. Поэтому в операциях над индексными деревьями есть две группы операций - как над деревьями значений атрибутов, так и над деревьями, включающими идентификаторы записей.
Для простоты будем оперировать разработанным ранее примером поддержки простых индексов:
Выборка поддерева с заданным значением атрибута.
Выборка поддерева со значениями атрибута, меньшими заданного.
Сократить дерево на один уровень, или трансформировать дерево - список значений + список идентификаторов в дерево - список идентификаторов:
Несложно видеть, что собственно сами операции на индексных структурах просты, если их описывать обобщенно, в косвенной форме, и сложность использования индексов проявляется тогда, когда их жестко прописывают в коде программ, используя предопределенные магические константы.
Подробнее о книге "MUMPS СУБД"
Структурно древовидный индекс удерживает как значения атрибутов, так и идентификаторы записей. Поэтому в операциях над индексными деревьями есть две группы операций - как над деревьями значений атрибутов, так и над деревьями, включающими идентификаторы записей.
Для простоты будем оперировать разработанным ранее примером поддержки простых индексов:
CreateRecords() k ^Index k ^Data n i,Figures,Colors,Counts,Figure,Color,Count,id s Figures="квадрат~круг~отрезок~треугольник" s Colors="красный~зелёный~синий~белый" s Counts="2~5~12~8" f i=1:1:12 d . s Figure=$p(Figures,"~",$r(4)+1) . s Color=$p(Colors,"~",$r(4)+1) . s Count=$p(Counts,"~",$r(4)+1) . s id=$$InsertRecord(Figure_"~"_Color_"~"_Count) q InsertRecord(RecordValues) n id s id=$i(^Data) l +^Data(id) s ^Data(id)=RecordValues d InsertIndexRecords(id,RecordValues) l -^Data(id) q id DeleteRecord(id) q:'$d(^Data(id)) l +^Data(id) n RecordValues s RecordValues=$g(^Data(id)) d DeleteIndexRecords(id,RecordValues) k ^Data(id) l -^Data(id) q UpdateRecord(id,RecordValues) q:'$d(^Data(id)) l +^Data(id) n OldRecordValues s OldRecordValues=$g(^Data(id)) d DeleteIndexRecords(id,OldRecordValues) s ^Data(id)=RecordValues d InsertIndexRecords(id,RecordValues) l -^Data(id) q InsertIndexRecords(id,RecordValues) d InsertIndexRecord("Figure",id,$p((RecordValues),"~",1)) d InsertIndexRecord("Color",id,$p((RecordValues),"~",2)) q DeleteIndexRecords(id,RecordValues) d DeleteIndexRecord("Figure",id,$p((RecordValues),"~",1)) d DeleteIndexRecord("Color",id,$p((RecordValues),"~",2)) q InsertIndexRecord(IndexName,id,Value) s ^Index(IndexName,Value,id)="" q DeleteIndexRecord(IndexName,id,Value) k ^Index(IndexName,Value,id) qРассмотрим операции над деревьями значений атрибутов. К ним можно отнести операции выборки поддерева с заданным значением атрибута, выбрать поддерево со значениями атрибута меньшими чем заданное, со значениями большими чем заданное, со значениями между двумя заданными, вычесть поддерево из другого поддерева, и получить число различных значений атрибутов. Приведем примерные реализации этих операций и как их использовать в контрольном примере.
Выборка поддерева с заданным значением атрибута.
EQ(ret,name) m @ret=@name q ret
USER>d EQ^TREEOP($NA(a),$na(^Index("Figure","круг")))Получить поддерево из заданного поддерева кроме указанного значения.
NE(ret,name,value) m @ret=@name k @root@(value) q NE2(ret,name,value...) m @ret=@name n i f i=1:1:value k:$d(value(i)) @ret@(value(i)) q USER>d NE^TREEOP($na(res), » $na(^Index("Figure")),"круг") USER>d NE2^TREEOP($na(res), » $na(^Index("Figure")),"круг","квадрат")Получили всё поддерево с индексом кроме поддерева с указанным значением. В первом случае стандартный М код, с вычитанием одного значения, во втором - с расширением COS, с вычитанием значений, заданных списком.
Выборка поддерева со значениями атрибута, меньшими заданного.
LT(ret,name,value) n i s i=value f s i=$o(@name@(i),-1) q:i="" m @ret@(i)=@name@(i) q
USER>d LT^TREEOP($na(r),$na(^Index("Figure")),"отрезок")Выборка поддерева со значениями атрибутов, большими чем заданное.
GT(ret,name,value) n i s i=value f s i=$o(@name@(i)) q:i="" m @ret@(i)=@name@(i) q
USER>k d GT^TREEOP($na(r),$na(^Index("Figure")),"отрезок")Выборка поддерева со значениями между двумя заданными.
BT(ret,name,begin,end) n i s i=begin f s i=$o(@name@(i)) q:(i="")!(i]]end)!(i=end) d . m @ret@(i)=@name@(i) q
USER>d BT^TREEOP($na(r),$na(^Index("Figure")), » "квадрат","треугольник")Получить число различных значений атрибутов.
COUNT(name) n ret,id s ret=0 s id="" f s id=$o(@name@(id)) q:id="" s ret=ret+1 q ret
USER>w $$COUNT^TREEOP($na(^Index("Figure","треугольник")))Рассмотрим операции с поддеревьями идентификаторов. К ним можно отнести трансформирование дерева - списка значений + списки идентификаторов в дерево списка идентификаторов, операцию объединения множеств (OR), операцию пересечения множеств (AND) и операцию дополнения множеств (SUB).
Сократить дерево на один уровень, или трансформировать дерево - список значений + список идентификаторов в дерево - список идентификаторов:
SIMPLE(ret,name) n i s i="" f s i=$o(@name@(i)) q:i="" m @ret=@name@(i) qПолучить идентификаторы, содержащиеся в индексе по полю Figure:
USER>d SIMPLE^TREEOP($na(r),$na(^Index("Figure")))Получить идентификаторы, у которых значение Figure лежит между заданными значениями:
USER>d BT^TREEOP($na(r2), » $na(^Index("Figure")),"квадрат","треугольник") USER>d SIMPLE^TREEOP($na(r),$na(r2))Получить объединение множеств:
OR(ret,names...) n i f i=1:1:names m:$d(names(i)) @ret=@(names(i)) qИспользуя эту операцию, получить идентификаторы записей, у которых значение Figure равно "круг" или "отрезок":
d OR^TREEOP($na(r),$na(^Index("Figure","круг")), » $na(^Index("Figure","отрезок")))Найти пересечение множеств:
AND(ret,names...) n id,i,j,k,place s id="" f s i=1 s id=$$ANDnext() q:id="" s @ret@(id)="" q ANDnext() ANDrep s id=$o(@names(i)@(id)) q:id="" "" f j=i+1:1:i+names-1 s place=((j-1)#names)+1 » i '$d(@names(place)@(id)) s i=place g ANDrep q idИспользуя операцию пересечения найти красные круги:
d AND^TREEOP($na(r),$na(^Index("Figure","круг")), » $na(^Index("Color","красный")))Найти дополнение множеств:
SUB(ret,from,what...) n i,id m @ret=@from f i=1:1:what d:$d(what(i)) . s id="" f s id=$o(@what(i)@(id)) q:id="" k @ret@(id) qИспользуя операцию дополнения, найти круги и не красные:
d SUB^TREEOP($na(r),$na(^Index("Figure","круг")), » $na(^Index("Color","красный")))Кроме приведенных операций в практике также встречаются другие, такие как взять первое или последнее значение, или взять начиная с n-го m значений. Для них также можно составить обобщенные операции, использующие косвенность аргумента.
Несложно видеть, что собственно сами операции на индексных структурах просты, если их описывать обобщенно, в косвенной форме, и сложность использования индексов проявляется тогда, когда их жестко прописывают в коде программ, используя предопределенные магические константы.
Подробнее о книге "MUMPS СУБД"
Комментариев нет:
Отправить комментарий