首页 » mongo

JAVA 遍历MONGO BSON 字段类型,BSON提供如何读取BSOn文档字段类型得方法

引入Mongo 依赖
 <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongodb-driver-async</artifactId>
            <version>3.4.2</version>
        </dependency>
        <!-- Sadly, we need the mongo-java-driver solely to serialize
             Document objects in a sane manner -->
        <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongo-java-driver</artifactId>
            <version>3.4.2</version>
        </dependency>
如果不需要连接mongo,只引入如下
  <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>bson</artifactId>
            <version>3.4.2</version>
        </dependency>
遍历文档字段,要借助BsonDocument和BsonValue来获取类型
 BsonDocument document = BsonDocument.parse(mogonDoc);
 MongoColumns column = new MongoColumns();

for(Map.Entry<String,BsonValue> en : document.entrySet()){
  BsonValue value = (BsonValue)en.getValue();
  String type = value.getBsonType().name();
}
BSON示例文档字符串,传入上面方法mogonDoc变量

BSON类型文档请见:https://docs.mongodb.com/manual/reference/bson-types/


{
    "_id" : ObjectId("6168e03a3f2817bf1f25e4fe"),
    "_class" : "com.pingan.lcloud.osp.FamilyInfo",
    "insNo" : "203669",
    "client_id" : "51A2E75F9EF64B638B123D445EB1239",
    "create_date" : ISODate("2021-09-24T01:38:45.202Z"),
    "personal_info" : {
        "client_id" : "51A2E75F9EF64B638B123D445EB1239",
        "name" : "小朱",
        "age" : 30,
        "sex" : "F",
        "birth_date" : "1992-05-30",
        "tel" : "",
        "operate_time" : ISODate("2021-09-20T19:34:03.202Z")
    }
}

我们经常碰到按某个key查询,然后sort的情况。尤其是热点数据(即经常limit 前 n条的数据),优化方案是,按{"sortKey" : 1, "queryCriteria" : 1} 建立索引。

1.有人可能疑惑,为什么,不按查询的queryCriteria排在前面呢,因为我们一般要先定位到查询的数据。这个是因为一个索引首先是一棵树。那么我们按sortkey在前的话,那么热点数据会集中在树的右边。又称--右平衡。我们limit的时候,几乎只遍历右边部分。虽然比queryCriteria 前面多便利了一部分记录,但是总体时间是比queryCriteria放前面快的。因为你queryCriteria找到以后,还要整个排序。相对很慢。
2.比如我们查询某篇文章的评论----按日期排序。那么我们一般只会获取前几页的评论。所以我们的符合索引如下:

db.comments.ensureIndex({"time" : 1, "articleId" : 1})
//查询时可以显式指定索引
db.comments.find({"articleId" : 3}).
... sort({"time" : -1}).
... hint({"time" : 1, "articleId" : 1}).

3.注意mongodb中,你point query 点查询---索引1和-1没有区别的,mongo可以从索引命中后的开头遍历,也可以从结尾遍历。但是 多值查询(multivalue) 如

db.users.find({"age" : {"$gte" : 21, "$lte" : 30}}).
... sort({"username" : 1}).

因为索引命中age比较多,那么排序索引的顺序就很重要了,一般建议直接按经常排序的方向建立索引。如果两个方向都有索引,就建立两个索引---不同的方向,如果我们这样建立索引

db.users.ensureIndex({"age" : 1, "username" : -1})

那么索引的排序如下:
mongo索引实际排序

最近需要同步mongodb数据到远程的mongodb实例,但是又没法组成replicaset,因为mongo要求replicaset必须互相能连通,就是互相都有识别对方的监听端口。而远程的monggodb实例无法链接---我本地的mongodb实例,因为我是局域网,没有公网ip

1.解决办法就是用mongodb connector,下载安装,mongo connector

sudo pacman -Sy
sudo pacman -S python 
sudo pacman -S python-pip
pip install mongo-connector

3.更改本地mongo为replSet模式,这里的members就一个,因为我本地就开了一个实例,目的主要是开启副本模式

config = {
"_id" : "mmm",
"members" : [
    {"_id" : 0, "host" : "127.0.0.1:27018"}
    ]
}

rs.initiate(config)

2.然后启动mongo connector就行了, xxx.xxx.xxx.xxx是我要同步数据到这个ip,所以我隐藏了

 mongo-connector -m localhost:27017 -t xxx.xxx.xxx.xxx:27017 -d mongo_doc_manager

3.惊喜的是,居然把我以前的数据全部同步过去了

No server chosen by WritableServerSelector from cluster description ClusterDescription,mongodb
过一段时间还会报错:Timed out after 30000 ms while waiting for a server that matches WritableServerSelector,这个原因是MOngodb只有一个实例,没有满足可以写的条件(mongo会根据大多数选票来决定master副本,master副本才可以写,大多数的条件是,至少3个副本才能进行大多数选举,生产上一般是5个),解决办法就是创建一个选举仲裁者Arbiters

1.运行下面的脚本,在master实例,我们就一个。

rs.addArb("localhost:27017")