最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Nebula?Graph介紹和SpringBoot環(huán)境連接和查詢操作

 更新時間:2022年10月12日 16:13:18   作者:Milton  
Nebula?Graph?是一款開源的、分布式的、易擴展的原生圖數(shù)據(jù)庫,能夠承載包含數(shù)千億個點和數(shù)萬億條邊的超大規(guī)模數(shù)據(jù)集,并且提供毫秒級查詢,這篇文章主要介紹了Nebula?Graph介紹和SpringBoot環(huán)境連接和查詢,需要的朋友可以參考下

說明

Nebula Graph 是一款開源的、分布式的、易擴展的原生圖數(shù)據(jù)庫,能夠承載包含數(shù)千億個點和數(shù)萬億條邊的超大規(guī)模數(shù)據(jù)集,并且提供毫秒級查詢。

  • 官網(wǎng):https://nebula-graph.com.cn/
  • segmentfault:https://segmentfault.com/t/nebula
  • 中文文檔:https://docs.nebula-graph.com.cn/3.1.0/1.introduction/2.1.path/
  • github:https://github.com/vesoft-inc/nebula
  • b站視頻:https://space.bilibili.com/472621355

當前Nebula Graph的最新版本是3.2.1, 根據(jù)官方的文檔進行配置
https://docs.nebula-graph.io/3.2.1/14.client/4.nebula-java-client/

  • 支持分布式. 相對于Neo4j, TigerGraph這些圖數(shù)據(jù)庫, Nebula 是面向分布式設(shè)計的, 因此對集群的支持比較完備, 在規(guī)模上上限要高很多. 在實際項目中存儲了180億的點邊, 這個數(shù)量對于Neo4j和TigerGraph是比較困難的.
  • 支持圖空間. 各個圖空間的ID是互不干擾的, 但是在同一個圖空間里ID的類型和長度必須一致. 注意這個一致約束的是所有的點和邊. Nebula 可以使用int64作為ID, 也可以用字符串, 但是字符串需要指定一個長度, 例如64個字節(jié). 相對于只能用長整數(shù)的Neo4j, ID設(shè)計上更自由靈活.
  • 點對應的類型叫TAG, 邊對應的類型叫EDGE

    TAG和EDGE都會對應一組的屬性(map, 或者說dict)

    一個點可以對多個TAG, 每個TAG一組屬性, 多組屬性. 項目中建議一開始不要用多TAG, 在整個圖結(jié)構(gòu)穩(wěn)定后, 再做合并

    一個邊只對應一個EDGE, 一組屬性

  • Nebula 用的是自定義的查詢語法 GQL, 和 cypher 語法基本一樣
  • 除了點邊的ID和關(guān)聯(lián)關(guān)系外, 只有帶索引的屬性可以查詢. 這點和其它圖數(shù)據(jù)庫不一樣, 其它數(shù)據(jù)庫即使沒有索引, 慢是慢點但是不報錯, Nebula直接給你返回錯誤.
  • 對于返回數(shù)量較大的查詢, Nebula會強制查詢必須帶limit
  • Nebula 單節(jié)點穩(wěn)定性是有問題的, 在3.2.1版本中觀察到偶爾會出現(xiàn)服務(wù)自行退出, 如果在生產(chǎn)環(huán)境使用, 需要有后臺監(jiān)控進行心跳檢測和自動啟動

GQL 常用查詢

下面列出一些常用的查詢

-- 列出圖空間
SHOW SPACES;
-- 列出tag(點類型)和edge(邊類型), 需要先 USE 一個圖空間
SHOW TAGS;
SHOW EDGES;

列出某一類型的點和邊

MATCH ()-[e:follow]-() RETURN e
MATCH (v:player) RETURN v

帶條件的查詢, 在結(jié)果數(shù)量較多時必須帶limit, 否則Nebula會報錯

match (v:ADDRESS)-[e]-() where id(v)==\"ADD:82388116\" return v,e limit 100

基礎(chǔ)配置和使用

在上面的鏈接中, 提供了最小的配置和測試代碼

pom.xml 增加包依賴

對于Nebula Graph 3.2.1, 需要使用3.0.0的版本. client的每個版本只能對應特定的一兩個服務(wù)端版本

<dependency>
	<groupId>com.vesoft</groupId>
	<artifactId>client</artifactId>
	<version>3.0.0</version>
</dependency>

Java調(diào)用

Java調(diào)用主要是三部分, 創(chuàng)建連接池, 創(chuàng)建會話, 執(zhí)行查詢

創(chuàng)建 NebulaPool 連接池

連接到地址127.0.0.1, 端口9669, 連接池大小100. 注意地址和端口是一個列表, Nebula是支持集群的. 連接時不需要用戶和密碼

NebulaPool pool = new NebulaPool();
try {
	NebulaPoolConfig nebulaPoolConfig = new NebulaPoolConfig();
	nebulaPoolConfig.setMaxConnSize(100);
	List<HostAddress> addresses = Arrays.asList(new HostAddress("127.0.0.1", 9669));
	Boolean initResult = pool.init(addresses, nebulaPoolConfig);
	if (!initResult) {
		log.error("pool init failed.");
		return;
	}
} catch ()
//...

創(chuàng)建 Session 會話

創(chuàng)建會話時需要用戶名和密碼

Session session = pool.getSession("root", "nebula", false);

執(zhí)行查詢

創(chuàng)建一個SPACE, 然后使用這個SPACE, 創(chuàng)建一個TAG person, 創(chuàng)建一個EDGE like

String createSchema = "CREATE SPACE IF NOT EXISTS test(vid_type=fixed_string(20)); "
		+ "USE test;"
		+ "CREATE TAG IF NOT EXISTS person(name string, age int);"
		+ "CREATE EDGE IF NOT EXISTS like(likeness double)";
ResultSet resp = session.execute(createSchema);
if (!resp.isSucceeded()) {
	log.error(String.format("Execute: `%s', failed: %s",
			createSchema, resp.getErrorMessage()));
	System.exit(1);
}

添加一個點記錄

String insertVertexes = "INSERT VERTEX person(name, age) VALUES "
		+ "'Bob':('Bob', 10), "
		+ "'Lily':('Lily', 9), "
		+ "'Tom':('Tom', 10), "
		+ "'Jerry':('Jerry', 13), "
		+ "'John':('John', 11);";
ResultSet resp = session.execute(insertVertexes);
if (!resp.isSucceeded()) {
	log.error(String.format("Execute: `%s', failed: %s",
			insertVertexes, resp.getErrorMessage()));
	System.exit(1);
}

查詢

String query = "GO FROM \"Bob\" OVER like "
		+ "YIELD $^.person.name, $^.person.age, like.likeness";
ResultSet resp = session.execute(query);
if (!resp.isSucceeded()) {
	log.error(String.format("Execute: `%s', failed: %s",
			query, resp.getErrorMessage()));
	System.exit(1);
}
printResult(resp);

在 SpringBoot 項目中使用 Nebula Graph

pom.xml 增加包依賴

<dependency>
	<groupId>com.vesoft</groupId>
	<artifactId>client</artifactId>
	<version>3.0.0</version>
</dependency>

Session工廠: NebulaSessionFactory.java

配合@Bean(destroyMethod = "close"), 創(chuàng)建一個工廠類, 接收pool并實現(xiàn)close()方法

public class NebulaSessionFactory {
    private final NebulaPool pool;
    private final String username;
    private final String password;

    public NebulaSessionFactory(NebulaPool pool, String username, String password) {
        this.pool = pool;
        this.username = username;
        this.password = password;
    }

    public Session getSession() {
        try {
            return pool.getSession(username, password, false);
        } catch (NotValidConnectionException|IOErrorException|AuthFailedException|ClientServerIncompatibleException e) {
            throw new RuntimeException("Nebula session exception", e);
        }
    }

    public void close() {
        pool.close();
    }
}

為什么不直接將 NebulaPool 配置為Bean? 因為 Session 每次創(chuàng)建時需要帶用戶名密碼, 將密碼作為config注入到每個Service中肯定是大家都不愿意看到的.

配置修改: application.yml

  • 這里的值如果不打算使用profile配置, 可以直接寫入
  • hosts是逗號分隔的地址端口列表, 例如 10.22.33.33:9669,10.22.33.34:9669
myapp:
  nebula:
    hosts: @nebula.hosts@
    username: @nebula.username@
    password: @nebula.password@
    max-conn: @nebula.max-conn@

Spring啟動配置: NebulaGraphConfig.java

應用啟動時讀取配置, 創(chuàng)建 NebulaPool, 并實例化 NebulaSessionFactory, destroyMethod = "close", 這個表示在項目shutdown時會調(diào)用Bean的close方法釋放資源.

@Configuration
public class NebulaGraphConfig {

    @Value("${myapp.nebula.hosts}")
    private String hosts;
    @Value("${myapp.nebula.max-conn}")
    private int maxConn;
    @Value("${myapp.nebula.username}")
    private String username;
    @Value("${myapp.nebula.password}")
    private String password;

    @Bean(destroyMethod = "close")
    public NebulaSessionFactory nebulaSessionFactory() {
        List<HostAddress> hostAddresses = new ArrayList<>();
        String[] hostList = hosts.split(",[ ]*");
        for (String host : hostList) {
            String[] hostParts = host.split(":");
            if (hostParts.length != 2 || !hostParts[1].matches("\\d+")) {
                throw new RuntimeException("Invalid host name set for Nebula: " + host);
            }
            hostAddresses.add(new HostAddress(hostParts[0], Integer.parseInt(hostParts[1])));
        }
        NebulaPoolConfig poolConfig = new NebulaPoolConfig();
        poolConfig.setMaxConnSize(maxConn);
        NebulaPool pool = new NebulaPool();
        try {
            pool.init(hostAddresses, poolConfig);
        } catch (UnknownHostException e) {
            throw new RuntimeException("Unknown Nebula hosts");
        }
        return new NebulaSessionFactory(pool, username, password);
    }
}

Service調(diào)用

在 Service 中進行調(diào)用

@Service
@Slf4j
public class GraphServiceImpl implements GraphService {

    @Autowired
    private NebulaSessionFactory sessionFactory;

    @Override
    public <T> NebulaResult<T> query(String graphSpace, String gql) {
        Session session = null;
        try {
            log.info("GQL: {}", gql);
            session = sessionFactory.getSession();
            NebulaResult<Void> res = query(session, "USE " + graphSpace);
            if (!res.isSuccess() || res.getResults() == null || res.getResults().size() == 0) {
                log.error("Failed to use space:{}", graphSpace);
                return null;
            }
            if (!graphSpace.equals(res.getResults().get(0).getSpaceName())) {
                log.error("Failed to use space:{}, result:{}", graphSpace, res.getResults().get(0).getSpaceName());
                return null;
            }
            return query(session, gql);
        } catch (IOErrorException e) {
            log.error(e.getMessage(), e);
            return null;
        } finally {
            if (session != null) {
                session.release();
            }
        }
    }

    private <T> NebulaResult<T> query(Session session, String gql) throws IOErrorException {
        String json = session.executeJson(gql);
        return JacksonUtil.extractByType(json, new TypeReference<>() {});
    }
}

輔助類 NebulaResult.java 等

外層結(jié)構(gòu)

這里定義了 json 格式響應的外層結(jié)構(gòu)

@Data
public class NebulaResult<T> implements Serializable {
    private List<Error> errors;
    private List<Result<T>> results;

    @JsonIgnore
    public boolean isSuccess() {
        return (errors != null && errors.size() == 1 && errors.get(0).getCode() == 0);
    }

    @Data
    public static class Error implements Serializable {
        private int code;
    }

    @Data
    @JsonIgnoreProperties(ignoreUnknown = true)
    @JsonInclude(JsonInclude.Include.NON_NULL)
    public static class Result<T> implements Serializable {
        private String spaceName;
        private List<Element<T>> data;
        private List<String> columns;
        private Error errors;
        private long latencyInUs;
    }

    @Data
    public static class Element<T> implements Serializable {
        private List<Meta<T>> meta;
        private List<Serializable> row;
    }

    @Data
    public static class Meta<T> implements Serializable {
        private String type;
        private T id;
    }
}

內(nèi)層因為區(qū)分Edge和Vertex, 結(jié)構(gòu)不一樣. 如果是混合返回的結(jié)果, 可以用 Serializable

String gql = "match (v:ADDR)-[e]-() where id(v)==\"ADD:123123\" return v,e limit 100";
        NebulaResult<Serializable> res = graphService.query("insurance", gql);
        log.info(JacksonUtil.compress(res));
        Assertions.assertThat(res).isNotNull();

對于邊, 需要使用結(jié)構(gòu)化的ID

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class EdgeId implements Serializable {
    private int ranking;
    private int type;
    private String dst;
    private String src;
    private String name;
}

用這個結(jié)構(gòu)進行查詢

NebulaResult<EdgeId> res3 = graphService.query("t_test1", "MATCH ()-[e:follow]-() RETURN e");

對于點, ID就是String

NebulaResult<String> res2 = graphService.query("t_test1", "MATCH (v:player) RETURN v");

到此這篇關(guān)于Nebula Graph介紹和SpringBoot環(huán)境連接和查詢的文章就介紹到這了,更多相關(guān)SpringBoot環(huán)境連接內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關(guān)文章

  • SpringBoot+slf4j線程池全鏈路調(diào)用日志跟蹤問題及解決思路(二)

    SpringBoot+slf4j線程池全鏈路調(diào)用日志跟蹤問題及解決思路(二)

    本文主要給大家介紹如何實現(xiàn)子線程中的traceId日志跟蹤,本文通過封裝Callable為例給大家介紹的非常詳細,需要的朋友一起看看吧
    2021-05-05
  • Spring聲明式事務(wù)注解之@EnableTransactionManagement解析

    Spring聲明式事務(wù)注解之@EnableTransactionManagement解析

    這篇文章主要介紹了Spring聲明式事務(wù)注解之@EnableTransactionManagement解析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • java格式化時間示例

    java格式化時間示例

    這篇文章主要介紹了java格式化時間示例,需要的朋友可以參考下
    2014-04-04
  • Java中字符串替換的4種方法代碼舉例

    Java中字符串替換的4種方法代碼舉例

    這篇文章主要介紹了Java中四種字符串替換方法,分別是String.replace()、String.replaceAll()、String.replaceFirst()和StringBuilder.replace(),并對比了它們的特點和適用場景,需要的朋友可以參考下
    2025-02-02
  • Java中的Monad設(shè)計模式及其實現(xiàn)過程

    Java中的Monad設(shè)計模式及其實現(xiàn)過程

    本文介紹了Java中的Monad設(shè)計模式及其在函數(shù)式編程中的應用,雖然Java不是函數(shù)式編程語言,但可以通過接口和泛型模擬Monad的行為,實現(xiàn)鏈式調(diào)用和上下文管理,通過一個示例展示了如何使用OptionalMonad進行鏈式調(diào)用,并解析了Monad接口和OptionalMonad的實現(xiàn)細節(jié)
    2025-03-03
  • 使用Log4j為項目配置日志輸出應用詳解以及示例演示的實現(xiàn)分析

    使用Log4j為項目配置日志輸出應用詳解以及示例演示的實現(xiàn)分析

    本篇文章是對Log4j為項目配置日志輸出應用詳解以及示例演示的實現(xiàn)進行了分析介紹,需要的朋友參考下
    2013-05-05
  • Spring @Bean注解配置及使用方法解析

    Spring @Bean注解配置及使用方法解析

    這篇文章主要介紹了Spring @Bean注解配置及使用方法解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-04-04
  • Java_Spring之Spring 中的事務(wù)控制

    Java_Spring之Spring 中的事務(wù)控制

    這篇文章主要介紹了Java Spring中的事務(wù)控制,事務(wù)控制要明確內(nèi)容,事務(wù)的控制都是基于AOP的,感興趣的小伙伴可以參考閱讀本文
    2023-04-04
  • Java模版引擎Freemarker

    Java模版引擎Freemarker

    FreeMarker是一個模板引擎,一個基于模板生成文本輸出的通用工具,使用純Java編寫 FreeMarker被設(shè)計用來生成HTML Web頁面,特別是基于MVC模式的應用程序
    2016-04-04
  • Java 程序內(nèi)部是如何執(zhí)行的?

    Java 程序內(nèi)部是如何執(zhí)行的?

    這篇文章主要介紹了Java 程序內(nèi)部是如何執(zhí)行的,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07

最新評論

邯郸市| 柘荣县| 特克斯县| 金沙县| 宁安市| 衡东县| 莫力| 边坝县| 五河县| 江津市| 广宁县| 宝山区| 濮阳市| 金川县| 潮州市| 库车县| 淮南市| 连江县| 石屏县| 嘉定区| 平和县| 五寨县| 平顶山市| 新竹县| 杨浦区| 常山县| 沙雅县| 乌兰浩特市| 迭部县| 济南市| 莫力| 自治县| 竹溪县| 凤阳县| 赤城县| 闻喜县| 甘南县| 辉南县| 巨鹿县| 重庆市| 泗阳县|