Nouvelle publication

Encontrar

Article
· Juil 1, 2024 4m de lecture

在InterSystems ObjectScript中使用 VECTORs

迄今为止,我看到的大多数使用向量vector的示例,将它只作为 SQL 中的一种功能,尤其是围绕 VECTOR_Search 的 3 个函数。
* TO_VECTOR()
* vector_dot_product ()
* vector_cosine ()

iris-vector-search 演示包中隐藏着一个非常有用的摘要。
从那里,你可以通过多个链接找到所需的一切。

我还缺少更多的 VECTOR 方法,于是在 Idea Portal 上提出了相关请求。

接着,我想起每个 SQL 方法或存储过程都有一堆 ObjectScript 代码。
于是我开始搜索,下面就是我的研究的一些总结:

%Library.Vector 是对新数据类型的核心描述
      这是一种复杂的结构,就像对象或 %DynamicObjects 或 $Bit Expressions 一样,需要特定的方式去访问。
我们还可以看到 2 个必备参数: 
      * DATATTYPE - 一旦设置就不能更改。 可接受的类型:  "整数integer"(或 "int")、"双精度浮点double"、"十进制decimal"、"字符串 "和 "时间戳"。
      * LEN >0 时,可以增长,但绝对不能缩小

$vector() / $ve() 是矢量访问的基本方法
      * 设置矢量数据 >>> SET $VE(. . .) = val
      * 返回矢量数据 >>> WRITE $VE(. . ) , SET var=$VE(. . ) 
          提示:单个位置返回值,但从::到位置返回另一个矢量!
      * 删除矢量数据 >> KILL $VE(. . .) 
      所有 3 个参数都需要至少 1 个位置参数。你可以把它理解为维度。

$isvector()显然是在开始操作前检查格式是否正确。

$vectorop() / $vop() 包括与向量有关的所有其他函数
    调用参数通常为(operation、vector)
某些operation提供可选的 bitxpr。它标记了要排除/包含的位置/维数。

例如: 
- 你只想对 x 轴和 y 轴进行操作,而不想对 z 轴进行操作。

单向量操作符

    Aggregate Operations 汇总操作
      * "count"
      * "max"
      * "min"
      * "sum"
    Filter Operations 过滤器操作
      * "defined"
      * "undefined"
      * "<"
      * "<="
      * ">"
      * ">="
      * "="
      * "!="
      * "between"
     Numeric Operations 数字相关操作
      * "+"
      * "-"
      * "/"
      * "*"
      * "**"
      * "#"
      * "e-"
      * "e/"
      * "ceiling"
      * "floor"
     String Operations 字符串相关操作
      * "_"
      * "e_"
      * "lower"
      * "upper"
      * "substring"
      * "trim"
      * "triml"
      * "trimr"
    Grouping Operations 组相关操作
     * "group"
     * "countgb"
   Miscellaneous Operations 杂项操作
     * "convert"
     * "length"
     * "mask"
     * "positions"
     * "set"
   Informative Operations 信息化业务
    * "bytesize"
    * "type"

多向量操作符(通常为两个操作)

    Vector-wise Filter Operations
       * "v<"
       * "v<="
       * "v>"
       * "v>="
       * "v="
       * "v!="
    Vector-wise Arithmetic Operations
      * "v+"
      * "v-"
      * "v/"
      * "v*"
      * "v**"
      * "v#"
    Vector Concatenation
      * "v_"
    Vector Grouping
      * "countg"
      * "maxg"
      * "ming"
      * "sumg"
    Vector Merge
     * "vset"

你看,现在已经有了一套丰富的工具。
如果你详细研究文档,结果的目的或优势可能不会立即显现出来。

不过,我希望你能对目前可用的工具有一个大致的了解。

Discussion (0)1
Connectez-vous ou inscrivez-vous pour continuer
Résumé
· Juil 1, 2024

InterSystems開発者コミュニティのダイジェスト、6月 2024

6月 2024開発者コミュニティ ニュースレターへようこそ。
全体統計
9 件の新しい投稿が公開 (6月 月):
 7件の新着記事
 2の新しい発表
5 人の新メンバーが参加 (6月 月)
1,309 件の投稿が公開 (全期間)
265 人のメンバーが参加 (全期間)
トップ記事
JSON_Table(SQL)の利用
Tomoko Furuzono順
今月のトップ作家
記事
お知らせ
6月, 2024Month at a GlanceInterSystems Developer Community
Résumé
· Juil 1, 2024

【週間ダイジェスト】 6/24 ~ 6/30 の開発者コミュニティへの投稿

6/24 ~ 6/30Week at a GlanceInterSystems Developer Community
Article
· Juin 30, 2024 1m de lecture

使用代码读取审计日志

你可以使用List query 对 %SYS.Audit 查询审计日志,代码如下:

 Set statement=##class(%SQL.Statement).%New()  
 Set status=statement.%PrepareClassQuery("%SYS.Audit","List")
 Set rs=statement.%Execute()  
 Set tab = $char(9)
 While rs.%Next() {    
   Write rs.%Get("TimeStamp")_tab_rs.%Get("Event")_tab_rs.%Get("Username"),!      
 }
Discussion (0)1
Connectez-vous ou inscrivez-vous pour continuer
Article
· Juin 30, 2024 7m de lecture

孤儿消息数据新手指南--如何清理 200 多 GB 的数据

Purpose of this article

有两篇很棒的有关删除消息关联的孤儿记录的内容以及如何处理孤儿的问题的WRC议最佳实践文章Ensemble Orphaned Messages | InterSystems Developer Community | Best DeleteHelper - A Class to Help with Deleting Referenced Persistent Classes (intersystems.com)
本文并不是要取代 Intersystems 专业人员撰写的这些文章,而是要在此基础上介绍我们如何利用这些信息和其他讨论(包括我们实际清理这些数据的方法)来帮助我们的数据库变得更加紧凑。

情况说明:

我们的备份越来越多。年初的时候,我们遇到过一台服务器被强制故障的情况,需要进行还原。由于数据库庞大,即使复制这个数据库也需要很长时间,更不用说还原重建shadow服务器了。因此,我们不得不决定最终解决这一增长问题。最初的原因已经确定 

  1. 开箱即用的任务或者在某些时候假定已运行,但没有勾选信息体。这是因为在查询其中一个消息体时,我们得到了来自 10 多年前的 ID 1。该任务是最佳实践中提到的默认 Ens.Util.Tasks.Purge。这就引出了流程中的提示 1 

理解你的数据

您在数据库中存储了哪些数据?您是否有必须保存在记录表中的数据?对于您的事务数据,我指的是与message header相关联的报文,您可以使用以下方法进行查询 

SELECT Distinct(MessageBodyClassName) from Ens.MessageHeader

最初,我会查看报文类,打开这些报文类,了解这些报文存储在哪个global中

这样,您就能在一定程度上了解数据的存储位置。

注意,如果您直接保存到数据流(如 %LIBRARY.GLOBALBINARYSTREAM)中,则表明存在孤儿,因为这些孤儿应保存到数据流容器中,我们稍后将介绍这一点


Running Global size report运行 GSize 是一目了然查看数据库大小的工具之一,它可以显示数据在数据库中的存储位置。在终端运行以下步骤 

do ^%GSIZE
Directory name: NAMESAPCE/ =>
All Globals? No => YES
Show details => NO

这可以说明数据在哪里被用掉,从而为您提供指导。

步骤 2 阻止未来的孤儿 

最佳实践指南中对此进行了很好的阐述,但我们还是对其中的步骤进行了细分。

  • 查找直接发送缓存流的类,并将代码迁移到使用流容器的类。
  • 查找未处理的嵌入类--添加手动删除和删除辅助工具 
  • 查看 hl7 消息的几个 %OnSaves 
步骤 3 清理孤儿数据
  1. 每天运行清理任务 
  2. 清理持久化流和其他杂项孤儿数据

 

使用直接流类的班级

Suriya Narayanan 指出,不应直接使用任何 %libary 类。如果不包含数据流,数据流最终会进入 ^Ens.Stream。这些数据不会以良好的引用方式存储,因此您必须在全局中查找您想要保留的最后数据。

在我们的场景中,是 BP 向操作发送消息,而不是将流添加到容器中。

set HTMLDocument=##class(%Library.GlobalBinaryStream).%New()
set tSC=..SendRequestSync(..DocmanRouterName,HTMLDocument, .aResponse,20,"")
//needed sent instead as container
set requestContainer = ##class(Ens.StreamContainer).%New()
set tSc=requestContainer.StreamSet(HTMLDocument)
set tSC=..SendRequestSync(..DocmanRouterName,requestContainer, .aResponse,20,"")
%Saves

并非所有在发送前 %save 的类都会导致问题,只有在没有发送的情况下才会。这种情况可能发生在修改经常保存的 hl7 副本时,也可能发生在临时保存但没有发送的情况下。下面是一个对 hl7 进行操作后没有保存的数据流示例,因此创建了 orpahans。有时,在清除了孤儿和监视器后,我就不会再创建孤儿了,下面的 %save 对象从未被使用过,因此是一个 orpahan,因为只发送了 hl7。在此之前有一个 %new 对象 

 嵌入式对象

下面的删除辅助文档就是一个例子。XML 信息在这方面是出了名的

Class Messages.XML.GenericWif.fileParameters Extends (%Persistent, %XML.Adaptor)
{
Property revisionNumber As %String;
Property primaryLink As Messages.XML.GenericWif.primaryLink;
Property additionalIndexes As Messages.XML.GenericWif.additionalIndexes;

在填充对象后,只有 Messages.XML.GenericWif.fileParameters 会被删除。

1) 进入每个对象,添加类方法和 OnDelete SQL 触发器,检查是否存在子对象并将其删除。可以使用 objectscript 或 sql 进行检查 

ClassMethod %OnDelete(oid As %ObjectIdentity) As %Status [ Private ]
{
      // Delete the property object references.
      Set tSC = $$$OK, tThis = ##class(Messages.XML.GenericWif.fileParameters).%Open(oid)
      If $ISOBJECT(tThis.primaryLink) Set tSC = ##class(Messages.XML.GenericWif.primaryLink).%DeleteId(tThis.primaryLink.%Id())
      If $ISOBJECT(tThis.additionalIndexes) Set tSC = ##class(Messages.XML.GenericWif.additionalIndexes).%DeleteId(tThis.additionalIndexes.%Id())
      Quit tSC
}

/// Callback/Trigger for SQL delete
Trigger OnDelete [ Event = DELETE ]
{
      // Delete the property object references. {%%ID} holds the id of the record being deleted.
      Set tID={%%ID}
      Set tThis = ##class(Messages.XML.GenericWif.fileParameters).%OpenId(tID)
      If $ISOBJECT(tThis.primaryLink) Do ##class(Messages.XML.GenericWif.primaryLink).%DeleteId(tThis.primaryLink.%Id())
      If $ISOBJECT(tThis.additionalIndexes) Do ##class(Messages.XML.GenericWif.additionalIndexes).%DeleteId(tThis.additionalIndexes.%Id())
      Quit
}

对于 objectscript,您可以打开其中一个 id,我们在测试系统或非生产系统上复制了该 id,例如,键入查询一条最旧的记录,然后在 sql 中查询其他表,例如 Messages_XML_GenericWif.primaryLink。然后,您可以查看是否可以打开其中的子 id。例如,您添加了代码,删除了包含嵌入式消息的 fileParameters 的 id 1。

set a = ##class(Messages.XML.GenericWif.primaryLink).%OpenId(2)
zw a 
//this output the info. Now delete parent
set tSC=##class(Messages.XML.GenericWif.fileParameters).%DeleteId(1)
set a = ##class(Messages.XML.GenericWif.primaryLink).%OpenId(2)
zw a 
//a should be ""

选项 2 是 deleteHelper。它的作用是在代码的 .int 中添加 %onDelete 类方法,而不是 sql。您只需在消息类的扩展中添加 deleteSuper 类,即 

Class Messages.BoltonRenal.Pathology.Outbound.PathologyResult Extends (Ens.Request, SRFT.Utility.DeleteHelper.OnDeleteSuper)
{
Property requestingClinician As %String;
Property department As Messages.BoltonRenal.Pathology.Outbound.Department;
// the on deletesuper is a class like this in the link
include Ensemble
/// A class to help assist in "deep" deleting of an instance, including references to other persistent classes.
/// <br><br>
/// To use simply add as a Super Class in your persistent class<br>
/// The class defines a Generator %OnDelete method that will generate code for your class, 
/// deleting, if needed, references (inclduing collections) to other persistent classes<br>
ClassMethod %OnDelete(oid As %ObjectIdentity) As %Status [ CodeMode = objectgenerator, Private, ServerOnly = 1 ]
{

	// a list ($ListBuild format) of "simple" (non-collection) property names we'll want to delete the references of (because they're Persistent)
	Set delPropNames = ""
                           

如果您转到routine、消息和 .int,就会发现嵌入的对象开始被删除,例如:

 

清理消息

在这一切之后,我们编写了自己的类来清除 150 天之外的信息。我们的想法如下 

  • 在数据查找表中设置要删除的自定义邮件类型(升级版可以将其存储在表格中,使代码更简洁
  • 手动设置删除最旧的 ens email正文。
  • 创建全局数据以存储结果。
  • 手动清理stream和其他残留物

再次提醒,请自行承担删除风险

我们的想法是,你有自己的报文正文类型列表(你的基础可能是 HL7 和报文正文详细信息)。

代码会在其中循环,并从报文头中获取最小 ID(对于报文正文,您需要查看保存到 messagebody 的最旧自定义报文),然后通过以下方式删除 

if msgBodyName="Ens.MessageBody"{
            set tMinMsgId=..MinBodyID
}else
{
    set tMinMsgId=..GetMinimumIDForMessage(rs.MessageBodyClassName)
}

// Min ID is just basically this query   set minIDQuery="SELECT  TOP(1) MessageBodyID  FROM Ens.MessageHeader where MessageBodyClassName=?"
And deletes it. Has added code around it to log 
  SET tSC1=$CLASSMETHOD(className,"%DeleteId",tResult.ID)
 

您可以尝试删除每种类型的数量。在运行 hl7 和报文体时,我们删除了 500000 个,而在运行报文体时,我们删除了 7200000 个。

同样,先在实时数据库的复刻环境(非生产或开发系统)上进行测试 

您不希望删除过多内容导致journal过大,因此需要反复试验。

 

 

如使用后丢失所需数据,我不承担任何责任。

清理流数据

我们有一个小任务,可以用来直接杀死global stream。更新数字并运行 .NET Framework 3.0。要非常清楚你应该保留的最新数据流编号是多少,而且只有当你剩下的数据流是连续的时才有效 

 

ClassMethod StreamPurge() As %Status
{
	set i=1
	while (i<200000){
		k ^CacheStream(i)
		s i=i+1
	}
	q $$$OK
}
Discussion (0)1
Connectez-vous ou inscrivez-vous pour continuer