SinoDB非关系型数据NoSQL

1.前言

  SinoDB支持JSON类型数据,用以支持NoSQL技术,使其将结构化数据和非结构化数据融合在一起,提供了一种混合数据库系统。SinoDB支持MongoDB的接口,可以使用MongoDB API来存储和操作NoSQL的JSON格式数据和关系型数据。SinoDB对SQL、NoSQL混合型应用支持灵活,应用平台广泛,可以实现关系型和非关系型数据库共存,减少迁移等带来的工作量,是应对超大规模和高并发数据的理想选择。NoSQL是非关系型数据存储的广义定义,它打破了长久以来关系型数据库与ACID理论大一统的局面。NoSQL数据存储不需要固定的表结构,其数据存储方式满足横向伸缩的应用体系结构需求。

2.SinoDB 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.2Mongo API支持NoSQL的JSON数据

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

3SinoDB操作NoSQL操作实践

3.1SQL语句访问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_id 1
(expression) {“city”:“fuzhou”,“country”:“China”,“population”:38000000}
place_id 2
(expression) {“mountain”:“Wuyishan”,“country”:“China”,“height”:1000}
place_id 3
(expression) {“national_park”:“Summer Palace”,“country”:“China”}

也可以在where条件中使用Sinoregal DS提供的内部函数对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.2MongoDB API操作NoSQL数据
SinoDB提供Wire Protocol Listener程序,用于支持服务器上的MongoDB驱动。通过使用JSON Wire Listener线程来访问JSON数据,使用的网络协议与MongoDB相同。该线程可将对JSON数据的操作转换成SQL语句及相应的函数调用。JSON Wire Listener原理图如下:
image

3.2.1Wire 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.3MongoDB 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 collection = db.getCollection(“tab1”);

c、插入数据
MongoCollection collection = mongoDatabase.getCollection(“tab1”);
//插入文档
/**

    1. 创建文档 org.bson.Document 参数为key-value的格式
    1. 创建文档集合List
    1. 将文档集合插入数据库集合中 mongoCollection.insertMany(List)
  • 插入单个文档可以用 mongoCollection.insertOne(Document)
    **/
    Document document = new Document(“title”, “mongo”)
    .append(“description”, “database”)
    .append(“likes”, 100).append(“by”, “Fly”);
    List documents = new ArrayList();
    documents.add(document);
    collection.insertMany(documents);

d、查询数据
MongoCollection collection = mongoDatabase.getCollection(“tab1”);
//检索所有文档
/**
*1. 获取迭代器FindIterable
*2. 获取游标MongoCursor
*3. 通过游标遍历检索出的文档集合
**/
FindIterable findIterable = collection.find();
MongoCursor mongoCursor = findIterable.iterator();
while(mongoCursor.hasNext()){
System.out.println(mongoCursor.next());
}

e、删除数据
MongoCollection collection = mongoDatabase.getCollection(“tab1”);
//删除符合条件的第一个文档
collection.deleteOne(Filters.eq(“likes”, 200));
//删除所有符合条件的文档
collection.deleteMany(Filters.eq(“likes”, 200));

f、更新数据
MongoCollection 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适用于混合型数据应用场景,开拓了新的业务模式,同时也为开发带来便捷。