SlideShare a Scribd company logo
1 of 17
Download to read offline
Собственные типы индексов
(они же функциональные индексы)
Конечный результат
Property A As %String;
Property B As %String;
Index someind On (A,B) As CustomPackage.CustomIndex;
Собственно квадродерево
Class SpatialIndex.Indexer {
Method %OnNew(indexGlobal As %String) As %Status
Method Insert(x As %Float, y As %Float, id As %String)
Method Delete(x As %Float, y As %Float, id As %String)
}
ClassMethod InsertIndex(pID, pArg... As %Binary) [ CodeMode = generator] {
if %mode'="method" {
set IndexGlobal = ..IndexLocation(%class,%property)
$$$GENERATE($C(9)_"set indexer = " _
"##class(SpatialIndex.Indexer).%New($Name("_IndexGlobal_"))")
$$$GENERATE($C(9)_"do indexer.Insert(pArg(1),pArg(2),pID)")
}
}
Class SpatialIndex.Index Extends %Library.FunctionalIndex
Пример использования
Class SpatialIndex.Test Extends %Persistent {
Property Name As %String(MAXLEN = 300);
Property Latitude As %String;
Property Longitude As %String;
Index coord On (Latitude, Longitude) As SpatialIndex.Index;
}
SpatialIndex.Test.1.INT
zcoordInsertIndex(pID,pArg...) public {
set indexer =
##class(SpatialIndex.Indexer).%New($Name(^SpatialIndex.TestI("coord")))
do indexer.Insert(pArg(1),pArg(2),pID)
}
zcoordUpdateIndex(pID,pArg...) public {
set indexer =
##class(SpatialIndex.Indexer).%New($Name(^SpatialIndex.TestI("coord")))
do indexer.Delete(pArg(3),pArg(4),pID)
do indexer.Insert(pArg(1),pArg(2),pID)
}
SpatialIndex.Test.1.INT
%SaveData(id) {
if insert {
// ...
do ..coordInsertIndex(id,i%Latitude,i%Longitude,"")
// ...
} else {
// ...
do ..coordUpdateIndex(id,i%Latitude,i%Longitude,zzc27v3,zzc27v2,"")
// ...
}
}
Так данные индекса выглядят в глобале
USER>zwrite ^SpatialIndex.TestI("coord")
^SpatialIndex.TestI("coord"," ")=$lb(-180,-90,180.0001,90.0001,0,0)
...
^SpatialIndex.TestI("coord"," 30")=$lb(.00005,.00005,90.000075,45.000075,0,0)
^SpatialIndex.TestI("coord"," 300")=$lb(.00005,.00005,45.0000625,22.5000625,1,0)
^SpatialIndex.TestI("coord"," 301")=$lb(45.0000625,.00005,90.000075,22.5000625,0,0)
^SpatialIndex.TestI("coord"," 3010")=$lb(45.0000625,.00005,67.50006875,11.25005625,1,0)
^SpatialIndex.TestI("coord"," 3011")=$lb(67.50006875,.00005,90.000075,11.25005625,1,0)
^SpatialIndex.TestI("coord"," 3012")=$lb(45.0000625,11.25005625,67.50006875,22.5000625,0,0)
^SpatialIndex.TestI("coord"," 30120")=$lb(45.0000625,11.25005625,56.250065625,16.875059375,1,0)
...
А как же запросы?
SELECT *
FROM SpatialIndex.Test
WHERE %ID %FIND search_index(coord, 'window',
'minx=56,miny=56,maxx=57,maxy=57')
Снова SpatialIndex.Indexer
ClassMethod Find(queryType As %Binary, queryParams As %String) As
%Library.Binary [ CodeMode = generator, SqlProc ]
{
if %mode'="method" {
set IndexGlobal = ..IndexLocation(%class,%property)
$$$GENERATE($C(9)_"set result = ##class(SpatialIndex.SQLResult).%New()")
$$$GENERATE($C(9)_"do result.PrepareFind($Name("_IndexGlobal_"),
queryType, queryParams)")
$$$GENERATE($C(9)_"quit result")
}
}
search_index(coord, 'window', 'minx=56,miny=56,maxx=57,maxy=57')
Метод, сгенерированный в SpatialIndex.Test.1.INT
zcoordFind(queryType,queryParams) public {
Set:'$isobject($get(%sqlcontext)) %sqlcontext=##class(%Library.ProcedureContext).%New()
set result = ##class(SpatialIndex.SQLResult).%New()
do result.PrepareFind($Name(^SpatialIndex.TestI("coord")), queryType,
queryParams)
quit result }
search_index(coord, 'window', 'minx=56,miny=56,maxx=57,maxy=57')
Class SpatialIndex.SQLResult Extends %SQL.AbstractFind
Property ResultBits [ MultiDimensional, Private ];
Method PrepareFind(indexGlobal As %String, queryType As %String, queryParams
As %Binary) As %Status {
// …
}
Method NextChunk(ByRef pChunk As %Integer = "") As %Binary
{
set pChunk = $order(i%ResultBits(pChunk),1,tBits)
quit:pChunk="" ""
quit tBits
}
Method ContainsItem(pItem As %String) As %Boolean
{
set tChunk = (pItem64000)+1, tPos=(pItem#64000)+1
quit $bit($get(i%ResultBits(tChunk)),tPos)
}
В итоге запросы выглядят так:
SELECT *
FROM SpatialIndex.Test
WHERE %ID %FIND
search_index(coord,'radius','x=55,y=55,radiusX=2,radiusY=2')
and name %StartsWith 'Z'
Параметр size предиката %FIND
SELECT *
FROM SpatialIndex.Test
WHERE name %startswith 'za'
and %ID %FIND
search_index(coord,'radius','x=55,y=55,radius=2')
size ((10))
Спасибо. Вопросы?
http://habrahabr.ru/company/intersystems/blog/272689/

More Related Content

Viewers also liked

Управление изменениями и коллективная разработка в Caché. InterSystems Meetup...
Управление изменениями и коллективная разработка в Caché. InterSystems Meetup...Управление изменениями и коллективная разработка в Caché. InterSystems Meetup...
Управление изменениями и коллективная разработка в Caché. InterSystems Meetup...InterSystems
 
Source Control Addon for InterSystems Caché with UDL support
Source Control Addon for InterSystems Caché with UDL supportSource Control Addon for InterSystems Caché with UDL support
Source Control Addon for InterSystems Caché with UDL supportInterSystems
 
Разработка мобильного и веб интерфейса для Caché
Разработка мобильного и веб интерфейса для CachéРазработка мобильного и веб интерфейса для Caché
Разработка мобильного и веб интерфейса для CachéInterSystems CEE
 
Caché github continuous intergration
Caché github continuous intergrationCaché github continuous intergration
Caché github continuous intergrationInterSystems
 
Приемы Сontinuous Integration при разработке приложений на Caché
Приемы Сontinuous Integration при разработке приложений на CachéПриемы Сontinuous Integration при разработке приложений на Caché
Приемы Сontinuous Integration при разработке приложений на CachéInterSystems CEE
 
InterSystems Caché Localization Manager
InterSystems Caché Localization Manager InterSystems Caché Localization Manager
InterSystems Caché Localization Manager InterSystems
 
Predicitive Analytics в InterSystems Caché
Predicitive Analytics в InterSystems CachéPredicitive Analytics в InterSystems Caché
Predicitive Analytics в InterSystems CachéInterSystems CEE
 
InterSystems Caché REST Forms
InterSystems Caché REST FormsInterSystems Caché REST Forms
InterSystems Caché REST FormsInterSystems
 
Основы Git
Основы GitОсновы Git
Основы Gitoelifantiev
 
How to build a case for change
How to build a case for changeHow to build a case for change
How to build a case for changethechangesource
 

Viewers also liked (10)

Управление изменениями и коллективная разработка в Caché. InterSystems Meetup...
Управление изменениями и коллективная разработка в Caché. InterSystems Meetup...Управление изменениями и коллективная разработка в Caché. InterSystems Meetup...
Управление изменениями и коллективная разработка в Caché. InterSystems Meetup...
 
Source Control Addon for InterSystems Caché with UDL support
Source Control Addon for InterSystems Caché with UDL supportSource Control Addon for InterSystems Caché with UDL support
Source Control Addon for InterSystems Caché with UDL support
 
Разработка мобильного и веб интерфейса для Caché
Разработка мобильного и веб интерфейса для CachéРазработка мобильного и веб интерфейса для Caché
Разработка мобильного и веб интерфейса для Caché
 
Caché github continuous intergration
Caché github continuous intergrationCaché github continuous intergration
Caché github continuous intergration
 
Приемы Сontinuous Integration при разработке приложений на Caché
Приемы Сontinuous Integration при разработке приложений на CachéПриемы Сontinuous Integration при разработке приложений на Caché
Приемы Сontinuous Integration при разработке приложений на Caché
 
InterSystems Caché Localization Manager
InterSystems Caché Localization Manager InterSystems Caché Localization Manager
InterSystems Caché Localization Manager
 
Predicitive Analytics в InterSystems Caché
Predicitive Analytics в InterSystems CachéPredicitive Analytics в InterSystems Caché
Predicitive Analytics в InterSystems Caché
 
InterSystems Caché REST Forms
InterSystems Caché REST FormsInterSystems Caché REST Forms
InterSystems Caché REST Forms
 
Основы Git
Основы GitОсновы Git
Основы Git
 
How to build a case for change
How to build a case for changeHow to build a case for change
How to build a case for change
 

Собственные типы индексов в СУБД Caché

  • 1. Собственные типы индексов (они же функциональные индексы)
  • 2. Конечный результат Property A As %String; Property B As %String; Index someind On (A,B) As CustomPackage.CustomIndex;
  • 3. Собственно квадродерево Class SpatialIndex.Indexer { Method %OnNew(indexGlobal As %String) As %Status Method Insert(x As %Float, y As %Float, id As %String) Method Delete(x As %Float, y As %Float, id As %String) }
  • 4.
  • 5.
  • 6. ClassMethod InsertIndex(pID, pArg... As %Binary) [ CodeMode = generator] { if %mode'="method" { set IndexGlobal = ..IndexLocation(%class,%property) $$$GENERATE($C(9)_"set indexer = " _ "##class(SpatialIndex.Indexer).%New($Name("_IndexGlobal_"))") $$$GENERATE($C(9)_"do indexer.Insert(pArg(1),pArg(2),pID)") } } Class SpatialIndex.Index Extends %Library.FunctionalIndex
  • 7. Пример использования Class SpatialIndex.Test Extends %Persistent { Property Name As %String(MAXLEN = 300); Property Latitude As %String; Property Longitude As %String; Index coord On (Latitude, Longitude) As SpatialIndex.Index; }
  • 8. SpatialIndex.Test.1.INT zcoordInsertIndex(pID,pArg...) public { set indexer = ##class(SpatialIndex.Indexer).%New($Name(^SpatialIndex.TestI("coord"))) do indexer.Insert(pArg(1),pArg(2),pID) } zcoordUpdateIndex(pID,pArg...) public { set indexer = ##class(SpatialIndex.Indexer).%New($Name(^SpatialIndex.TestI("coord"))) do indexer.Delete(pArg(3),pArg(4),pID) do indexer.Insert(pArg(1),pArg(2),pID) }
  • 9. SpatialIndex.Test.1.INT %SaveData(id) { if insert { // ... do ..coordInsertIndex(id,i%Latitude,i%Longitude,"") // ... } else { // ... do ..coordUpdateIndex(id,i%Latitude,i%Longitude,zzc27v3,zzc27v2,"") // ... } }
  • 10. Так данные индекса выглядят в глобале USER>zwrite ^SpatialIndex.TestI("coord") ^SpatialIndex.TestI("coord"," ")=$lb(-180,-90,180.0001,90.0001,0,0) ... ^SpatialIndex.TestI("coord"," 30")=$lb(.00005,.00005,90.000075,45.000075,0,0) ^SpatialIndex.TestI("coord"," 300")=$lb(.00005,.00005,45.0000625,22.5000625,1,0) ^SpatialIndex.TestI("coord"," 301")=$lb(45.0000625,.00005,90.000075,22.5000625,0,0) ^SpatialIndex.TestI("coord"," 3010")=$lb(45.0000625,.00005,67.50006875,11.25005625,1,0) ^SpatialIndex.TestI("coord"," 3011")=$lb(67.50006875,.00005,90.000075,11.25005625,1,0) ^SpatialIndex.TestI("coord"," 3012")=$lb(45.0000625,11.25005625,67.50006875,22.5000625,0,0) ^SpatialIndex.TestI("coord"," 30120")=$lb(45.0000625,11.25005625,56.250065625,16.875059375,1,0) ...
  • 11. А как же запросы? SELECT * FROM SpatialIndex.Test WHERE %ID %FIND search_index(coord, 'window', 'minx=56,miny=56,maxx=57,maxy=57')
  • 12. Снова SpatialIndex.Indexer ClassMethod Find(queryType As %Binary, queryParams As %String) As %Library.Binary [ CodeMode = generator, SqlProc ] { if %mode'="method" { set IndexGlobal = ..IndexLocation(%class,%property) $$$GENERATE($C(9)_"set result = ##class(SpatialIndex.SQLResult).%New()") $$$GENERATE($C(9)_"do result.PrepareFind($Name("_IndexGlobal_"), queryType, queryParams)") $$$GENERATE($C(9)_"quit result") } } search_index(coord, 'window', 'minx=56,miny=56,maxx=57,maxy=57')
  • 13. Метод, сгенерированный в SpatialIndex.Test.1.INT zcoordFind(queryType,queryParams) public { Set:'$isobject($get(%sqlcontext)) %sqlcontext=##class(%Library.ProcedureContext).%New() set result = ##class(SpatialIndex.SQLResult).%New() do result.PrepareFind($Name(^SpatialIndex.TestI("coord")), queryType, queryParams) quit result } search_index(coord, 'window', 'minx=56,miny=56,maxx=57,maxy=57')
  • 14. Class SpatialIndex.SQLResult Extends %SQL.AbstractFind Property ResultBits [ MultiDimensional, Private ]; Method PrepareFind(indexGlobal As %String, queryType As %String, queryParams As %Binary) As %Status { // … } Method NextChunk(ByRef pChunk As %Integer = "") As %Binary { set pChunk = $order(i%ResultBits(pChunk),1,tBits) quit:pChunk="" "" quit tBits } Method ContainsItem(pItem As %String) As %Boolean { set tChunk = (pItem64000)+1, tPos=(pItem#64000)+1 quit $bit($get(i%ResultBits(tChunk)),tPos) }
  • 15. В итоге запросы выглядят так: SELECT * FROM SpatialIndex.Test WHERE %ID %FIND search_index(coord,'radius','x=55,y=55,radiusX=2,radiusY=2') and name %StartsWith 'Z'
  • 16. Параметр size предиката %FIND SELECT * FROM SpatialIndex.Test WHERE name %startswith 'za' and %ID %FIND search_index(coord,'radius','x=55,y=55,radius=2') size ((10))