Java SDK对接向量数据库
本文介绍如何使用Java语言调用openGauss向量数据库
要求
- 安装java1.8及以上版本
- Apache Maven
安装SDK
- 在线安装
开发者可以直接从maven中央仓库中获取jar包maven中央仓库下载,也可以在openGauss官网下载社区官网下载,运行以下命令安装Java SDK
1. <dependency>
2. <groupId>org.opengauss</groupId>
3. <artifactId>opengauss-jdbc</artifactId>
4. <version>your version</version>
5. </dependency>
- 离线安装
1) 可以从开源社区下载openGauss-connector-jdbc源码
1. git clone https://gitcode.com/opengauss/openGauss-connector-jdbc.git
切换到代码目录运行sh build.sh,成功编译后会出现两个jar包,分别是opengauss-jdbc-${version}.jar与postgresql.jar(在output目录下)
2) 可以直接获取相关jdbc的压缩包 获取链接:https://download-opengauss.osinfra.cn/archive_test/7.0.0-RC2/openGauss7.0.0-RC2.B019/openEuler20.03/arm/openGauss-JDBC-7.0.0-RC2.tar.gz,可以根据操作系统版本和服务器架构自行选择对应压缩包,压缩包解压后得到opengauss-jdbc-${version}.jar与postgresql.jar。
基本操作
1.连接数据库
1. public Connection getConnection(String username, String passwd)
2. {
3. String driver = "org.opengauss.Driver";
4. String sourceURL = "jdbc:opengauss://localhost:port/database_name";
5. Connection conn = null;
7. try {
8. Class.forName(driver).getDeclaredConstructor().newInstance();
9. } catch(Exception e) {
10. e.printStackTrace();
11. return null;
12. }
13. try {
14. conn = DriverManager.getConnection(sourceURL, username, passwd);
15. System.out.println("Connection succeed!");
16. } catch(Exception e) {
17. e.printStackTrace();
18. return null;
19. }
20. return conn;
21. }
2.创建表
1. // 执行普通SQL语句
2. public void ExecuteSQL(Connection conn, String sql)
3. {
4. Statement stmt = null;
5. try {
6. stmt = conn.createStatement();
7. int rc = stmt.executeUpdate(sql);
8. stmt.close();
9. } catch (SQLException e) {
10. if (stmt != null) {
11. try {
12. stmt.close();
13. } catch (SQLException e1) {
14. e1.printStackTrace();
15. }
16. }
17. e.printStackTrace();
18. }
19. }
21. public void CreateTable(Connection conn, int dim)
22. {
23. String sql = String.format("CREATE TABLE IF NOT EXISTS demotable(id INTEGER, content TEXT, embedding vector(%d));", dim);
24. ExecuteSQL(conn, sql);
25. }
3.创建索引
1. // 用L2距离创建HNSW类型的向量索引
2. public void CreateIndex(Connection conn)
3. {
4. String sql = String.format("CREATE INDEX ON demotable USING hnsw (embedding vector_l2_ops);");
5. ExecuteSQL(conn, sql);
6. }
4.插入/删除/更新
- 插入
1. public void InsertDataSingle(Connection conn, int id, String content, String vector)
2. {
3. String sql = String.format("INSERT INTO demotable VALUES(%d, '%s', '%s');", id, content, vector);
4. ExecuteSQL(conn, sql);
5. }
- 删除
1. public void DeleteData(Connection conn)
2. {
3. String sql = String.format("DELETE FROM demotable where id > 10;");
4. ExecuteSQL(conn, sql);
5. }
- 更新
1. public void UpdateData(Connection conn, String vector)
2. {
3. String sql = String.format("UPDATE demotable set embedding = '%s' where id = 10;", vector);
4. ExecuteSQL(conn, sql);
5. }
5.查询
1. public String findNearestVectors(Connection conn, int efsearch, String vector, int topK)
2. {
3. Statement statement = null;
4. ResultSet resultSet = null;
5. String res = "";
6. // 设置查询参数
7. String paramsql = String.format("set hnsw_ef_search = %d;", efsearch);
8. ExecuteSQL(conn, paramsql);
9. String querysql = String.format("SELECT * FROM demotable ORDER BY embedding <-> '%s' LIMIT %d;", vector, topK);
10. try {
11. statement = conn.createStatement();
12. resultSet = statement.executeQuery(querysql);
13. while (resultSet.next()) {
14. int id = resultSet.getInt("id");
15. String content = resultSet.getString("content");
16. Object embed = resultSet.getObject("embedding");
17. // 替换成你希望的结果
18. res += "id: " + id + ", content: " + content + ",embedding: " + embed + "\n";
19. }
20. } catch (Exception e) {
21. e.printStackTrace();
22. } finally {
23. try { if (resultSet != null) resultSet.close(); } catch(Exception e) {}
24. try { if (statement != null) statement.close(); } catch(Exception e) {}
25. }
26. return res;
27. }
6.多向量并发查询
多向量召回支持在单次搜索请求中同时提交多个查询向量,openGauss将并行对查询向量进行搜索,并返回多组结果。
函数名
1. public List<List<Map<String, Object>>> executeMultiSearch(Map<String, String> dbConfig,
2. String sqlTemplate, List<List<Object>> parameters, Map<String, Object> scanParams, int threadCount)
输入参数
- dbConfig:数据库连接配置,包含jdbcUrl、user、password
- sqlTemplate:查询语句,要求是单条查询语句(select为首单词)、包含向量操作符(<->/<=>/<#>/<+>/<~>/<%>)
- parameters:查询参数,要求不为空
- scanParams:需要通过set设置的参数(如hnsw_ef_search、nprobes)
- threadCount:连接池最大连接数,和数据库最大连接数(由参数max_connections设置)有关,由于java使用的HikariCP连接池在创建阶段并没有预设置数据库连接,一般来说,同一时间内执行请求的最大连接数要小于数据库最大连接数,但是数据库对于管理员用户的连接限制会略超过max_connections设置。
输出参数
- 查询结果,形式为
[[{id=1, embedding='[1,2,3]'},{id=2, embedding='[2,2,2]'}], [],...],表示n个查询向量对应的limit个结果。
使用案例
1. import java.util.*;
2. import org.opengauss.util.ParallelSearch
4. String jdbcUrl = "jdbc:opengauss://localhost:port/dbname?allowMultiQueries=true";
5. Map<String, String> dbConfig = new HashMap<>();
6. dbConfig.put("jdbcUrl", jdbcUrl);
7. dbConfig.put("username", "YourName");
8. dbConfig.put("auth", "YourPassword");
10. String sqlTemplate = "select id from demotable order by embedding <-> '?'::vector limit ?;";
11. int threadCount = 2;
12. Map<String, Object> scanParams = new HashMap<>();
13. scanParams.put("enable_seqscan", "off");
14. scanParams.put("hnsw_ef_search", 40);
16. List<List<Object>> parameters = new ArrayList<>();
17. parameters.add(new ArrayList<>(Arrays.asList(Arrays.toString(new int[]{1, 2, 3})), 1));
18. parameters.add(new ArrayList<>(Arrays.asList(Arrays.toString(new int[]{2, 2, 3})), 2));
20. ParallelSearch ps = new ParallelSearch();
21. List<List<Map<String, Object>>> res = ps.executeMultiSearch(dbConfig, sqlTemplate, parameters, scanParams, threadCount);
用例
编译及运行命令:
1. javac -cp ./openGauss-connector-jdbc/output/opengauss-jdbc-7.0.0-RC2.jar <yourfilename>.java
2. java -cp ./openGauss-connector-jdbc/output/opengauss-jdbc-7.0.0-RC2.jar:. <yourfilename>
1. public static void main(String[] args) {
2. String username = "test2"; // 替换为你的用户名
3. String password = "YourPassword"; // 替换为你的密码
4. int embeddingDim = 3;
6. Connection conn = getConnection(username, password);
7. if (conn != null) {
8. CreateTable(conn, embeddingDim);
9. CreateIndex(conn);
10. InsertDataSingle(conn, 0, "test", "[1,2,3]");
11. DeleteData(conn);
12. UpdateData(conn, "[1,1,1]");
13. String res=findNearestVectors(conn, 20, "[2,2,2]", 2);
14. System.out.println("连接成功!"+res);
15. try {
16. conn.close();
17. System.out.println("连接已关闭。");
18. } catch (SQLException e) {
19. e.printStackTrace();
20. }
21. }
22. }
