Nova postagem

Pesquisar

Artigo
· jan 25 14min de leitura

GraphRAG Inside InterSystems IRIS: Hybrid Retrieval for Fraud Detection (and other complex problems)

TL;DR: This article demonstrates how to run GraphRAG-style hybrid retrieval—combining vector similarity, graph traversal, and full-text search—entirely within InterSystems IRIS using the iris-vector-graph package. We use a fraud detection scenario to show how graph patterns reveal what vector search alone would miss.

Discussão (0)1
Entre ou crie uma conta para continuar
Artigo
· jan 25 4min de leitura

使用 JDBC 将 Java 连接到 InterSystems IRIS

在上一篇文章中,我们谈到了 ODBC 和 C# 连接,现在让我们看看 JDBC 和 Java。InterSystems JDBC 驱动程序是集成 Java 应用程序的高性能推荐方式。

以下是使用 JDBC 驱动程序将 Java 应用程序连接到 IRIS 实例的分步指南。

第 1 步:获取并包含 InterSystems IRIS JDBC 驱动程序

JDBC 驱动程序与 ODBC 驱动程序不同,后者通常安装在整个系统中,而 JDBC 驱动程序通常以JAR 文件的形式发布,必须包含在 Java 项目的类路径中。

如果 InterSystems IRIS 安装在本地计算机或您可以访问的其他计算机上,您可以在 install-dir/dev/java/lib/ 或类似位置找到该文件,其中 install-dir 是实例的安装目录。反之,您也可以从驱动程序软件包页面下载 jar 文件。

或者按照 @Dmitry Maslennikov 在评论中的建议 ,使用 Maven 的maven 中央仓库

<dependency>
    <groupId>com.intersystems</groupId>
    <artifactId>intersystems-jdbc</artifactId>
    <version>3.10.5</version>
</dependency>

或 Gradle:

implementation("com.intersystems:intersystems-jdbc:3.10.5")

在项目中包含 jar 文件:

  • Maven/Gradle:如果使用构建工具,最简单的方法是将 InterSystems JDBC 驱动程序作为依赖项添加到 pom.xmlbuild.gradle 文件中。这会自动下载并管理 JAR。
  • 手册:对于简单的项目,必须将 JAR 文件放在项目目录(如 /lib)中,并在编译和运行时将其明确添加到 classpath 中。

第 2 步:定义 JDBC 连接

JDBC 连接 URL 明确规定了 Java 应用程序连接数据库的位置和方式。其格式为 jdbc:<subprotocol>://<host>:<port>/<namespace>

InterSystems IRIS 的格式为

String url = "jdbc:IRIS://127.0.0.1:1972/USER";
String user = "_System";
String password = "SYS";

注意:

  • 驱动程序前缀jdbc:IRIS
  • 127.0.0.1 是服务器地址(远程连接时更改)。
  • 1972 是 IRIS超级服务器端口(标准端口通常为 1972 或 51773)。
  • USER 是代码和数据所在的 InterSystems IRIS 目标命名空间
  • 默认的 user_System,密码是 SYS请务必在生产环境中更改这些默认值。

第 3 步:用 Java 实现连接

我们将使用标准java.sql包建立连接并执行查询。

下面是一个最小的 Java 示例,它连接到 IRIS,针对默认表执行简单查询,并使用try-with-resources显示结果,以实现可靠的连接管理。

package com.example;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
	
public class IrisJdbcConnector {

    public static void main(String[] args) {
        
        // 1. Define the connection details
        String url = "jdbc:IRIS://127.0.0.1:1972/USER";
        String user = "_System";
        String password = "SYS";
        
        int maxId = 5; // Parameter for the query
        // The try-with-resources block ensures all resources are closed automatically
        try (
            // 2. Establish the connection
            Connection conn = DriverManager.getConnection(url, user, password);
            
            // 3. Define the SQL Query using a placeholder (?)
            PreparedStatement pstmt = conn.prepareStatement("SELECT ID, Name, DOB FROM Sample.Person WHERE ID < ?")
        ) {
            System.out.println("Connection to InterSystems IRIS successful!");

            // 4. Bind the parameter value
            pstmt.setInt(1, maxId);

            // 5. Execute the query
            try (ResultSet rs = pstmt.executeQuery()) {
                
                System.out.println("--- Query Results ---");
                
                // 6. Iterate through the results
                while (rs.next()) {
                    // Access data by column name
                    int id = rs.getInt("ID");
                    String name = rs.getString("Name");
                    // JDBC automatically handles the mapping of IRIS types to Java types (e.g., Date)
                    String dob = rs.getDate("DOB").toString(); 
                    
                    System.out.println(String.format("ID: %d, Name: %s, DOB: %s", id, name, dob));
                }
            }
            
        } catch (SQLException e) {
            // 7. Handle JDBC-specific exceptions (e.g., connection failure, invalid SQL)
            System.err.println("\n--- Database Error ---");
            System.err.println("SQL State: " + e.getSQLState());
            System.err.println("Error Message: " + e.getMessage());
            System.err.println("Ensure the IRIS server is running and the JDBC driver JAR is in the classpath.");
        } catch (Exception e) {
            System.err.println("\n--- General Error ---");
            System.err.println(e.getMessage());
        }
    }
}

❗与所有数据库连接一样,在生产代码中始终使用预处理语句(类似于参数化查询),以防止 SQL 注入漏洞。

Discussão (0)1
Entre ou crie uma conta para continuar
InterSystems Oficial
· jan 25

InterSystems任命Don Woodlock为总裁

2026 年 1 月 6 日,马萨诸塞州 波士顿——创新数据技术公司InterSystems今日宣布,即日起,Don Woodlock被任命为总裁,全面负责领导公司的日常运营工作。在领导公司长达47年之后,创始人、所有者兼首席执行官Phillip “Terry” Ragon将卸下日常管理职责,转而专注于指导公司的业务和技术战略。Ragon将继续担任首席执行官一职,并与领导团队紧密合作,确保公司平稳过渡,继续秉持对卓越品质和客户成功的承诺。
“在2023年全球峰会上发言时,我谈到了强大而稳定的文化如何具有韧性,以及文化为何是预测未来成功最有力的指标。”Ragon表示,"我相信,我们在InterSystems所建立的文化真正实现了自我延续,现在是时候让下一代来接棒,成为我们所有人共同努力成果的管理者了。"
Woodlock已在InterSystems担任医疗业务副总裁长达八年。他拥有深厚的行业专业知识和敏锐的技术洞察力,并与公司“以客户为先”的文化理念高度契合。

"自2017年加入InterSystems以来,Terry一直是我的榜样和导师。"Woodlock表示,"早在几十年前,我就开始接触和使用InterSystems的产品,起初是担任技术职务,后来则领导一个为医疗健康领域提供解决方案的业务部门。这些来自一线的真实客户经验,再结合InterSystems在技术、财务和组织方面的优势,激发了我帮助公司迈向下一个成功时代的激情。”

点击这里,认识我们的领导团队

Discussão (0)1
Entre ou crie uma conta para continuar
Resumo
· jan 25

InterSystems 开发者社区中文版:每周摘要(1月19日-25日)

一月 19 - 25, 2026Week at a GlanceInterSystems Developer Community
Artigo
· jan 25 4min de leitura

Ways to store and query lists and arrays in IRIS

As mentioned in the previous article, it is possible to configure the way you wish your collections to be stored and queried in SQL.

To set this up, you will need to use the following field parameters and settings:

The STORAGEDEFAULT parameter tells the IRIS compiler which physical data structure to use when writing a collection to a Global.

For a list of properties, the default value is "list", meaning that the data is serialized into a single string using $LISTBUILD (an internal binary format). It is stored as part of the main object’s data node in the global.

For an array of properties, the default value is "array", meaning that each element is stored in a separate global subnode. This essentially creates a "child" structure on the disk. It is best for large collections where you need to update or delete single items without rewriting the entire record.

But, at the same time, you can toggle these settings, and you can force a List to act like an Array (and vice versa) for performance reasons. For example,

Property Notes As list of %String (STORAGEDEFAULT = "array");

This will store the list in subnodes, making individual item updates much faster.

To go further, you can tell the system how you wish your data to be mapped in SQL. For this, use the field parameter SQLPROJECTION. It is the most powerful tool for making collections "visible" to SQL.

Value SQL Representation Description
"column" Single Column The entire collection appears as one field. Lists show up as a delimited string or $LIST.
"table" Child Table IRIS automatically generates a secondary table linked by a Foreign Key (the parent's ID).
"table/column" Dual Projection The property appears both as a field in the main table and as a separate child table.

You can set both column and table setting to both list and array.

Beyond the big two, several parameters influence the nuances of how these collections behave in SQL.

SqlListType  (for list properties only), as mentioned in the previous article, defines the format of the data when it is projected as a single column, and can get one of the following values:

  • LIST (default) returns the internal IRIS $LIST format. Best for IRIS-to-IRIS integrations.
  • DELIMITED returns a string separated by a character (defined by SqlListDelimiter ). Best for legacy CSV exports or simple reporting.
  • SUBNODE - the data is physically stored in subnodes (like an array) but seen in SQL as a single field.

When SQLPROJECTION =  "table" is used, these determine the naming convention:

  • SQLTABLENAME - name of the generated child table (e.g., Employee_Phones)
  • SQLFIELDNAME - name of the value column within that child table

Now let's look at the example. Let's say we have the following class:

Class CRM.Contact Extends (%Persistent, %Populate) [ SqlRowIdName = Contact_PK ]
{

/// 1. Standard Property: Custom SQL field name
Property FullName As %String(MAXLEN = 100) [ SqlFieldName = Contact_Name ];

/// 2. Simple List: Projected as a single column
/// Reason: Use this for small sets of data where you just need to see them in one cell.
/// Goal: Compatibility with legacy tools using comma-delimited strings.
Property Tags As list Of %String [ SqlFieldName = Category_Tags, SqlListType = DELIMITED ];

/// 3. Performance-Optimized List: Projected as a Child Table
/// Reason: 'STORAGEDEFAULT = array' ensures that adding a 10th phone number 
///         doesn't require rewriting the whole contact record (O(1) vs O(N)).
/// Goal: Allow BI tools to JOIN on phone numbers without complex parsing.
Property PhoneNumbers As list Of %String(SQLPROJECTION = "table", SQLTABLENAME = "Contact_Phones", STORAGEDEFAULT = "array");

/// 4. Key-Value Array: Projected as a Table
/// Reason: Arrays are naturally stored as subnodes. Projecting as a table 
///         allows SQL users to query specific keys easily.
Property Metadata As array Of %String(SQLPROJECTION = "table", SQLTABLENAME = "Contact_Metadata");
}

If we now create 10 instances of this class, we can execute the following queries and see the results:

SELECT *
  FROM CRM.Contact

So we can see that the FullName field is called Contact_Name, the primary field is called Contact_PK and the only other field we have is Category_Tags that is a delimited list.

At the same time, we have 2 additional tables: CRM.Contact_Metadata and CRM.Contact_Phones

If we execute the query

SELECT *
  FROM CRM.Contact_Phones

we will see that our list of PhoneNumbers actually looks like it's an array with the primary key from the main table (CRM.Contact), primary key of this table which is a composition of the Contact PK and position of the data in the list, list data and the position of the data in the list:

If we execute the query

SELECT *
  FROM CRM.Contact_Metadata

we will see a usual table with the primary key from the main table (CRM.Contact), primary key of this table, which is a composition of the Contact PK and array key, array key, and array data:

So basically, the difference between the last two results is that for the list represented as a table, the element_key is the position of the element in the list, and for the array - it's the actual key.

Hopefully, this will help you to make an informed decision on how you would like to store and represent your collections!

Discussão (0)0
Entre ou crie uma conta para continuar