К операциям с древовидными индексами относятся операции, использующие деревья с
индексами и реализующие над ними теоретико - множественные операции. К таким
операциям
относят логические операции над множествами: 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 СУБД"
Комментариев нет:
Отправить комментарий