SinoDB非关系型数据NoSQL实践

2022-05-24 00:00:00 数据 文档 操作 支持 提供

1、前言

        SinoDB为适应IT技术的发展,引入支持JSON类型数据,用以支持NoSQL技术,使其将结构化数据和非结构化数据融合在一起,提供了一种混合数据库系统。SinoDB支持MongoDB的接口,可以使用MongoDB API来存储和操作NoSQL的JSON格式数据和关系型数据。SinoDB对SQL、NoSQL混合型应用支持灵活,应用平台广泛,可以实现关系型和非关系型数据库共存,减少迁移等带来的工作量,是应对超大规模和高并发数据的理想选择。

       NoSQL是非关系型数据存储的广义定义,它打破了长久以来关系型数据库与ACID理论大一统的局面。NoSQL数据存储不需要固定的表结构,其数据存储方式满足横向伸缩的应用体系结构需求。

 2SinoDB NoSQL介绍

       SinoDB支持使用SQL语句来存取NoSQL的JSON数据,也支持通过使用Mongo API来存取NoSQL的JSON数据,二者在数据库中的存储都是采用BSON(binaryJSON)类型。

 2.1  标准SQL支持NoSQL的JSON数据

SinoDB提供如下函数,用于支持使用SQL语句来操作NoSQL的JSON数据,如下:

bson_value_int(lvarchar doc, lvarchar key) returns bigint

bson_value_bigint(lvarchar doc, lvarchar key) returns bigint

bson_value_double(lvarchar doc, lvarchar key) returns float

bson_value_lvarchar(lvarchar doc, lvarchar key) returns lvarchar as string

bson_value_document(lvarchar doc, lvarchar key) returns lvarchar as BSON object

bson_value_array(lvarchar doc, lvarchar key) returns lvarchar as  BSON array

bson_value_binary(lvarchar doc, lvarchar key) returns lvarchar as binary

bson_value_objectid(lvarchar doc, lvarchar key) returns lvarchar as string

bson_value_boolean(lvarchar doc, lvarchar key) returns boolean

bson_value_date(lvarchar doc, lvarchar key) returns datetime

bson_value_code(lvarchar doc, lvarchar key) returns lvarchar as string

bson_value_timestamp(lvarchar doc, lvarchar key) returns datetime

bson_key_exists(lvarchar doc, lvarchar key) returns Boolean

 2.2  Mongo API支持NoSQL的JSON数据

       SinoDB提供Wire Protocol Listener程序,用于支持服务器上的MongoDB驱动。在SinoDB中,Wire Protocol Listener就像一个开关,打开数据库服务器上的监听程序后,可以使用Java、PHP、Python等语言通过MongoDB API来操作JSON数据。在应用层,数据操作采用JSON格式,Wire Protocol Listener程序会把接收到的JSON数据转换成SQL的形式,然后让数据库服务进行处理。

3 、SinoDB 操作NoSQL操作实践

3.1 SQL语句访问NoSQL的JSON数据

SinoDB支持JSON数据类型。这个新的数据类型可以通过SinoDB提供的内部函数,使其能被普通的SQL语句操作。例如:一个旅游系统中,某张表用来存储不同游客的观光信息,可以用JSON的数据来记录其观光地点——访问的城市、地区、岛屿、景点等。我们可以定义如下表:

create table places (

    place_id SERIAL,

    place BSON);

 SinoDB提供了一些函数供我们使用,可以通过普通的SQL插入数据。

INSERT INTO places VALUES (1, '{city: "fuzhou", country: "China", population: 38000000}'::JSON);

INSERT INTO places VALUES (2, '{mountain: "Wuyishan", country: "China", height: 1000}'::JSON);

INSERT INTO places VALUES (3, '{national_park: "Summer Palace", country: "China"}'::JSON);

 从上面语句可以看出,插入place字段的值需要符合JSON格式,符合JSON格式的数据在后续查询时才能使用SinoDB提供的内部函数对其进行操作。查询语句如下:

SELECT place_id, place::JSON FROM places

结果:

place_id1

(expression)  {"city":"fuzhou","country":"China","population":38000000}

place_id2

(expression)  {"mountain":"Wuyishan","country":"China","height":1000}

place_id3

(expression) {"national_park":"Summer Palace","country":"China"}

也可以在where条件中使用SinoDB提供的内部函数对NoSQL的JSON数据进行过滤:

SELECT *, place::JSON FROM places

WHERE bson_value_lvarchar (place, 'country') = 'China';

SELECT *, place::JSON FROM places

WHERE bson_value_lvarchar (place, 'country') IS NULL;

SELECT *, place::JSON FROM places

WHERE bson_value_lvarchar (place, 'mountain') IS NOT NULL

AND bson_value_int (place, 'height') >= 1000;

SELECT *, place::JSON FROM places

WHERE bson_value_lvarchar (place, 'country') = 'China'

AND bson_value_lvarchar (place, 'national_park') IS NOT NULL;

另外,SinoDB提供一个genBSON函数,用于从关系型数据中生成JSON的数据,这样就可以把关系型数据迁移到NoSQL中。例如:

create table cities (

  city_id SERIAL,

  city CHAR(30),

  population INT,

  country CHAR(30));

INSERT INTO places

SELECT 0, genBSON(ROW(city, country, population), 0, 1)::JSON

FROM cities;

当然,如果为了保持数据各自的独立性,我们也可以采用创建视图的方式:

CREATE VIEW places_and_cities (place) AS

  SELECT place::JSON FROM places

  UNION

  SELECT genBSON(ROW(city, country, population), 0, 1)::JSON FROM cities;

 3.2  MongoDB API操作NoSQL数据

       SinoDB提供Wire Protocol Listener程序,用于支持服务器上的MongoDB驱动。通过使用JSON Wire Listener线程来访问JSON数据,使用的网络协议与MongoDB相同。该线程可将对JSON数据的操作转换成SQL语句及相应的函数调用。JSON Wire Listener原理图如下:


3.2.1 Wire Protocol Listener配置

在SinoDB安装目录的etc目录下,复制jsonListener-example.properties文件为jsonListener.properties文件,并修改文件中的URL及security.sql.passthrough参数。例如:

cp etc/jsonListener-example.properties etc/jsonListener.properties

vi jsonListener.properties

url=jdbc:informix-sqli://IP:port/sysmaster:INFORMIXSERVER=sinoregal;USER=informix;PASSWORD=informix

security.sql.passthrough=true

3.2.2 启动监听程序

java -cp $INFORMIXDIR/bin/jsonListener.jar com.ibm.nosql.server.ListenerCLI -config $INFORMIXDIR/etc/jsonListener.properties –start

3.2.3 Mongo Shell操作SinoDB NoSQL

在SinoDB中,创建table1集合,并用Mongo Shell插入数据到table1中。

创建集合指令:

db.createCollection("table1")

在集合table1中写入数据:

db.table1.insert({id:1, name:’mongo’});

db.table1.insert({id:2, name:’sinoregal’});

db.table1.insert({id:3, name:’DB2’});

db.table1.insert({id:4, name:’oracle’});

db.table1.insert({id:5, name:’mysql’});

查询table1集合指令:

db.table1.find(),返回如下结果:

{“_id”:ObjectId(“531d9a8b12w8wvb666d3442a”),”id”:1, “name”:”mongo”}

{“_id”:ObjectId(“531d9a8b12w8wvb666d3442b”),”id”:2, “name”:”sinoregal”}

{“_id”:ObjectId(“531d9a8b12w8wvb666d3442c”),”id”:3, “name”:”DB2”}

{“_id”:ObjectId(“531d9a8b12w8wvb666d3442d”),”id”:4, “name”:”oracle”}

{“_id”:ObjectId(“531d9a8b12w8wvb666d3442e”),”id”:5, “name”:”mysql”}

从以上可以看出,使用Mongo Shell操作SinoDB的NoSQL,可以直接采用MongoDB的指令。

3.2.4 MongoDB Java API操作NoSQL数据

通过MongoDB Java API操作NoSQL数据除了启动Wire Protocol Listener外,只需要在代码中引入mongo-java-driver-*.*.*.jar依赖包即可。用MongoDB Java API操作NoSQL数据只要按照MongoDB的语法即可,无需做任何变动。下面给出采用MongoDB Java API操作NoSQL的具体示例:

a、在java类中引用MongoDB相关类:

import com.mongodb.MongoClient;

import com.mongodb.client.FindIterable;

import com.mongodb.client.MongoCollection;

import com.mongodb.client.MongoCursor;

import com.mongodb.client.MongoDatabase;

import com.mongodb.client.model.Filters;

b、连接数据库,获取tab1的Collection

//连接到Mongodb服务

MongoClient mongoClient = new MongoClient("192.168.216.123",27017);

// 连接到数据库

MongoDatabase db = mongoClient.getDatabase("stores_demo");

//获取tab1的Collection

MongoCollection<Document> collection = db.getCollection("tab1");

c、插入数据

MongoCollection<Document> collection = mongoDatabase.getCollection("tab1");

//插入文档/**

* 1. 创建文档 org.bson.Document 参数为key-value的格式

* 2. 创建文档集合List<Document>

* 3. 将文档集合插入数据库集合中 mongoCollection.insertMany(List<Document>)

* 插入单个文档可以用 mongoCollection.insertOne(Document)**/

Document document = new Document("title", "mongo")

                                .append("description", "database")

                                .append("likes", 100).append("by", "Fly");

List<Document> documents = new ArrayList<Document>();

documents.add(document);

collection.insertMany(documents);

d、查询数据

MongoCollection<Document> collection = mongoDatabase.getCollection("tab1");

//检索所有文档/**

 *1. 获取迭代器FindIterable<Document>

 *2. 获取游标MongoCursor<Document>

 *3. 通过游标遍历检索出的文档集合 **/

FindIterable<Document> findIterable = collection.find();

MongoCursor<Document> mongoCursor = findIterable.iterator();

while(mongoCursor.hasNext()){

System.out.println(mongoCursor.next());}

e、删除数据

MongoCollection<Document> collection = mongoDatabase.getCollection("tab1");

//删除符合条件的个文档

collection.deleteOne(Filters.eq("likes", 200));

//删除所有符合条件的文档

collection.deleteMany(Filters.eq("likes", 200));

f、更新数据

MongoCollection<Document> collection = mongoDatabase.getCollection("tab1");

//更新文档 将文档中likes=100的文档修改为likes=200

collection.updateMany(Filters.eq("likes", 100), new Document("$set",new Document("likes",200)));

 4、总结

       SinoDB通过引入支持JSON类型数据,使结构化和非结构化数据能够在一个数据库中统一共存,提供了一种混合数据库系统,并支持绝大部分NoSQL功能。由此可见,SinoDB适用于混合型数据应用场景,开拓了新的业务模式,同时也为开发带来便捷。

相关文章