About neohope

一直在努力,还没想过要放弃...

MongoDB主从数据库(Shell)

1、主数据库

mongod --dbpath=D:\Database\MongoDB3\dbm --port=27017 --master

2、从数据库

mongod --dbpath=D:\Database\MongoDB3\dbs1\ --port=27018 --slave --source=localhost:27017

3、后期指定主数据库

mongod --dbpath=D:\Database\MongoDB3\dbs2\ --port=27019 --slave 

mongo localhost:27019
use local
db.sources.insert({"host":"localhost:27017"})
db.sources.find()

条码分类

1、一维条码
一维条码是由一组规则排列的条、空以及对应的字符组成的标记,“条”指对光线反射率较低的部分,“空”指对光线反射率较高的部分,这些条和空组成的数据表达一定的信息,并能够用特定的设备识读,转换成与计算机兼容的二进制和十进制信息。根据不同使用环境,会有不同码制,即不同条码条和空的排列规则,常用的一维码的码制包括:EAN码、39码、交叉25码、UPC码、128码、93码,ISBN码,及Codabar(库德巴码)。

常用一维条码

2、堆叠式/行排式/称堆积式/层排式二维条码
其编码原理是建立在一维条码基础之上,按需要堆积成二行或多行。它在编码设计、校验原理、识读方式等方面继承了一维条码的一些特点,识读设备与条码印刷与一维条码技术兼容。但由于行数的增加,需要对行进行判定,其译码算法与软件也不完全相同于一维条码。有代表性的行排式二维条码有:Code 16K、Code 49、PDF417、MicroPDF417 等。

3、矩阵式/棋盘式二维条码
其编码原理是在一个矩形空间通过黑、白像素在矩阵中的不同分布进行编码。在矩阵相应元素位置上,用点(方点、圆点或其他形状)的出现表示二进制“1”,点的不出现表示二进制的“0”,点的排列组合确定了矩阵式二维条码所代表的意义。矩阵式二维条码是建立在计算机图像处理技术、组合编码原理等基础上的一种新型图形符号自动识读处理码制。具有代表性的矩阵式二维条码有:Code One、MaxiCode、QR Code、 Data Matrix、Han Xin Code、Grid Matrix 等。

常用二维条码

参考:
维-基-百-科(转图片了,方便大家看)

MongoDB查询使用Codec的简单示例(java)

1、数据准备

db.person.insert({"name":"neo","age":"26","sex":"male"})
db.person.insert({"name":"joe","age":"28","sex":"male"})

2、使用Codec

class Person  
{
       public ObjectId _id;
       public double Age;  
       public String Name;  
       public String Sex;  
       
       public Person(ObjectId _id, String Name, double Age, String Sex)
       {
    	   this._id=_id;
    	   this.Name=Name;
    	   this.Age=Age;
    	   this.Sex=Sex;
       }
}

class PersonCodec implements Codec<Person> 
{
    private final CodecRegistry codecRegistry;

    public PersonCodec(final CodecRegistry codecRegistry) {
        this.codecRegistry = codecRegistry;
    }
    
    @Override
    public void encode(BsonWriter writer, Person t, EncoderContext ec) {
    	 writer.writeStartDocument();
         writer.writeName("_id");
         writer.writeObjectId(t._id);
         writer.writeName("name");
         writer.writeString(t.Name);
         writer.writeName("age");
         writer.writeDouble(t.Age);
         writer.writeName("sex");
         writer.writeString(t.Sex);
         writer.writeEndDocument();
    }

    @Override
    public Class<Person> getEncoderClass() {
        return Person.class;
    }

    @Override
    public Person decode(BsonReader reader, DecoderContext dc) 
    {
        reader.readStartDocument();
        reader.readName();
        ObjectId _id = reader.readObjectId();
        reader.readName();
        String name = reader.readString();
        reader.readName();
        double age = reader.readDouble();
        reader.readName();
        String sex =reader.readString();
        reader.readEndDocument();
        return new Person(_id,name,age,sex);
    }
}

class PersonCodecProvider implements CodecProvider 
{
    @Override
    public <T> Codec<T> get(Class<T> type, CodecRegistry cr) 
    {
        if (type == Person.class) 
        {
            return (Codec<T>) new PersonCodec(cr);
        }
        return null;
    }
}

public class CodecTest 
{
	private static void testCodec()
	{
		String[] hosts = {"127.0.0.1"};
		int port = 27017;
		String user = null;
		String password = null;
		String database = "test";
		CodecRegistry codecRegistry = CodecRegistries.fromRegistries(
	            CodecRegistries.fromProviders(new PersonCodecProvider()),
	            MongoClient.getDefaultCodecRegistry());  
		
		MongoClient mongoClient = getConnection(hosts,port,user,password,database,codecRegistry);
		MongoDatabase db = mongoClient.getDatabase("test");
		MongoCollection<Person> collection = db.getCollection("person",Person.class);
		FindIterable<Person> iterable = collection.find();
		MongoCursor<Person> cursor = iterable.iterator();
		while (cursor.hasNext())
		{
        		Person p  = cursor.next();
        		System.out.println("personName: " + p.Name);
		}
	}
	
	private static MongoClient getConnection(String[] hosts, int port, String user, String password, String database, CodecRegistry codecRegistry)
	{
	        MongoClientOptions mongoClientOptions = new MongoClientOptions.Builder()
	        .connectionsPerHost(100)
	        .threadsAllowedToBlockForConnectionMultiplier(5)
	        .maxWaitTime(1000 * 60 * 2)
	        .connectTimeout(1000 * 10)
	        .socketTimeout(0)
	        .socketKeepAlive(false)
	        .readPreference(ReadPreference.primary())
	        .writeConcern(WriteConcern.ACKNOWLEDGED)
	        .codecRegistry(codecRegistry)
	        .build();
		
		List<ServerAddress> mongoAddresses = new ArrayList<ServerAddress>();
		for (String host : hosts) {
		    mongoAddresses.add(new ServerAddress(host, port));
		}
		
		List<MongoCredential> mongoCredentials = null;
		if (user != null && !user.isEmpty() && password != null && !password.isEmpty()) {
		    mongoCredentials = new ArrayList<MongoCredential>();
		    mongoCredentials.add(MongoCredential.createMongoCRCredential(user, database, password.toCharArray()));
		}
		
		if(mongoCredentials==null)
		{
			return new MongoClient(mongoAddresses, mongoClientOptions);
		}
		else
		{
			return new MongoClient(mongoAddresses, mongoCredentials, mongoClientOptions);
		}
	}
}

MongoDB的MapReduce简单示例(java)

1、数据准备

db.sell.insert({"price":8.0,"amount":500.0,"status":"a"})
db.sell.insert({"price":8.0,"amount":450.0,"status":"a"})
db.sell.insert({"price":8.0,"amount":400.0,"status":"a"})
db.sell.insert({"price":9.0,"amount":350.0,"status":"a"})
db.sell.insert({"price":9.0,"amount":300.0,"status":"a"})
db.sell.insert({"price":9.0,"amount":250.0,"status":"a"})
db.sell.insert({"price":9.0,"amount":200.0,"status":"a"})
db.sell.insert({"price":10.0,"amount":150.0,"status":"d"})
db.sell.insert({"price":10.0,"amount":100.0,"status":"d"})
db.sell.insert({"price":10.0,"amount":50.0,"status":"d"})
db.sell.insert({"price":10.0,"amount":0.0,"status":"d"})

2、MapReduce

	private static void testMapReduce3x()
	{
		MongoClient mongoClient = new MongoClient("localhost", 27017);
		MongoDatabase db = mongoClient.getDatabase("test");
		MongoCollection collection = db.getCollection("sell");

		String map = "function(){emit(this.price,this.amount);}";
		String reduce = "function(key, values){return Array.sum(values)}";

		MapReduceIterable out = collection.mapReduce(map, reduce);
		MongoCursor cursor = out.iterator();
		while (cursor.hasNext()) 
		{
			System.out.println(cursor.next());
		}
	}
	
	private static void testMapReduce2x()
	{
		MongoClient mongoClient = new MongoClient("localhost", 27017);
		MongoDatabase db = mongoClient.getDatabase("test");
		BasicDBObject query=new BasicDBObject("status","a");
		DBCollection dbcollection = mongoClient.getDB("test").getCollection("sell");
		
		String map = "function(){emit(this.price,this.amount);}";
		String reduce = "function(key, values){return Array.sum(values)}";
		
		MapReduceCommand cmd = new MapReduceCommand(dbcollection, map, reduce,
		    "outputCollection", MapReduceCommand.OutputType.INLINE, query);
		
		MapReduceOutput out2 = dbcollection.mapReduce(cmd);
		for (DBObject o : out2.results()) 
		{
		   System.out.println(o.toString());
		}
	}

下一次技术进步是什么呢

恩,我说的是技术进步,不是技术革命哦。

个人认为,比较近的一次技术进步有可能为能源的进步,或者说是电池的进步。
电池现在其实是遇到了很大的瓶颈。
随便打开一个智能手机后盖,至少三分之一是电池,而且瞬间会耗光。

另一个进步,就是屏幕的进步,
或者说,可能不再需要特定的屏幕了,
桌面,皮肤,衣服,都可以作为屏幕,甚至这些都不需要。

然后,就是可穿戴设备的进步,
前两个进步完成后,可穿戴设备才会真的牛起来。
现在的可穿戴设备,还没有真正能超越智能手机的。

另外,AI还没有跟上来哦,需要真正天才的指引,这个需要的是技术革命哦。

其他的吗,就要看物理的发展啦。

为什么DICOM不适合差异化压缩

前几天,同事参加了一个技术讨论会,会间有人热烈的讨论了DICOM影像的单序列多幅的差异化压缩。

想法很简单,就是类似于视频压缩的方法,找出关键帧影像,对非关键帧影像就可以做差异化压缩了。

说实话,我认为这种做法没什么实际价值,原因如下:

1、现在存储很便宜,存储量已经不是什么大问题,但存储的读写速度却一直上不来(SSD太贵),这才是现在要解决的首要问题,所以现在有些人在尝试用HDFS这样的分布式存储系统,来解决这个问题,同时可以解决可靠性

2、DICOM本身没有关键帧的概念,每一幅扫描的人体部位都不同,差距都不小,差异化压缩效果不一定好

3、DICOM文件原本可以独立打开,差异化压缩后,一个关键帧出了问题,其余非关键帧就都报废了,可靠性其实是降低了

4、DICOM影像的每一幅都有MetaData,差异压缩后MetaData如何存储,也是个问题

5、同时,这些计算太消耗CPU了,而且其他厂商并不支持这种压缩方法

PS:
其实有一种解决方案是这样的,将多个DICOM文件合并为一个更大的文件,并记录每个文件的位置索引,支持顺序和随机读写
这样可以大幅提升存取效率,规避LOSF问题,本身就可以降低存储的使用,并且更适配HDFS
已经申请专利了

移动医疗不应该按打车模式推进

现在一些移动医疗的厂商,在做产品的时候,完全采用了打车模式进行推进。

甚至开始照抄出租、专车模式,出来了现有医院、新建医院模式。

但他们忽略了一个问题。

那就是医疗,并不像打车,有如此多的线下资源可以调用。

有几个明显的现象要注意:
1、中国的医疗资源十分匮乏
2、中国的医疗资源过于集中
3、越好的医生越忙,越难以到线上
4、好的医院,不缺患者;
5、看病和打车不一样,不是是个医院你就敢去,是个人你就让他给你治疗
不信?那我问下,如果是你关心的人生病了,你会随便找家医院看看,还是各种打听哪里靠谱?

那问题就来了,即使能有医生到线上,人数有限不说,水平也不会很高。
新建医院,需要有医院的实体,这样成本就高了,而且医生整体数量,不会呈爆炸性增加。
所以,不会像打车软件这样,一呼百应,这个并非不能为的事情,而是一个要持之以恒的工作。

那有哪些是讨巧,现在又能推进的呢:
1、把学医的学生拉到线上,他们不一定有行医资格,但有医疗知识,可以做咨询、网上导诊,这是个不错的开始,比如丁香园就在做
2、用好退休医生队伍,他们经验丰富,有一定闲散时间,但对互联网及移动设备使用不熟练,需要更易用的软件及设备
3、推动国内的社区医院,我们现在的社区医院形同虚设,社区医院的价值根本没有体现出来,其实小问题就应该在社区医院搞定。这个出现的原因,上面已经说到了。解决的方式应该是与政府合作,才会长久。
4、私人诊所,比如牙医、私人医生,这样的服务,这个有美国模式可以借鉴。但要等待政策。
5、远程预诊,缺少专业易用廉价的设备
6、大集团化医院,这个建议几个巨头联合起来,在一二线城市,进行推动。打响品牌战。
7、快速做好远程会诊、诊断、手术等

其实,大家烧钱的地方太集中,另外有几个市场被低估了:
1、运动健身。没有特别专业厂商在做,其实已经可以开展起来了。
2、健康咨询。营养咨询、健身指导、心理咨询、幼儿护理、产前培训。
3、幼老年护理。你懂的。
4、真正的可穿戴设备,现在都是Baby Product,呵呵。
5、需要一个很强势的协会,制定标准,造福人类。

哪些医疗数据可以用HDFS

其实,几年前就有人和我建议,希望在医院用Hadoop,用云计算,来处理医院的日常业务。
但他们苦于找不到接入点。

在建设平台的过程中,更有口号说,不管数据格式如何,先收集上来再说。
但这样做的结果,往往是,数据收上来了,但获取数据的时候,却无法提供。

更有很多供应商,买了第三方的ESB、MQ等商业软件,直接卖给医院,告诉医院,这就是平台。
结果,医院根本就不会用这些产品,整个一悲剧。

但到今天,放眼望去,在医院中,建立私有云的,还是少之又少,主要原因如下:
1、缺少专业人才。医院的运维人员有限,主要以Windows系统的维护为主,日常工作十分的繁杂。没有精力及经验来维护以Linux为基础的云。
2、医疗行业相对保守,出了问题责任重大。很多医院不是不愿意,而是不敢使用新技术,不敢做第一个吃螃蟹的人。
3、现在没有好的厂商,提供优质的私有云建设服务。而医院用Windows、SQL Servr、Oracle远远多于Linux+MySQL+开源非关系数据库的原因,就是商业产品出了问题,还有人帮忙解决,而开源产品出了问题,可是举目无亲。
4、医疗资源的保密性,让医院不敢将资料放到公有云上
5、多数医疗资源,变更频繁,不适合与云存储(云存储适合量大、变更少、变更时尽量不要更新而要追加)
6、很多医院的各个科室,互联互通都没有做好,还在补课阶段

其实,从文件特性上看,还是有不少内容可以放到云上的:
1、影像数据。其实医院的影像文件,采集后,一般经过无损压缩,会N年不再修改。所以放射、核医学、超声、内镜、病理的影像数据,完全可以放到HDFS上。取回速度,会快很多。
2、归档后的病历数据。归档后的病历资料,也是很少变化的,数量也比较巨大,种类也很多,很适合HDFS存储。
3、医院的OA及资产等历史资料,也可以进行HDFS存储

待续。。。

MBP调整硬盘分区(后记)

总结了一下,应该的流程为:

1、在MBP下,用Win7自带功能缩小分区
2、MBP的硬盘取下,调整为移动硬盘,接到虚拟机上,直接Ghost备份
3、MBP硬盘安回去,到MAC下调整分区
4、MBP的硬盘取下,调整为移动硬盘,接到虚拟机上,直接Ghost还原
5、用PE修复Win7的启动项
6、MBP硬盘安回去,就可以进入Win7了
7、进入MAC,备份原装硬盘的数据
8、删除分区
9、进入Win7,扩展分区
10、进入MAC,调整GPT分区表

这样就搞定了,而且不用处理光驱问题。

MBP调整硬盘分区

我的MBP,是2011 Early,如果你体验过它的妖娆,你就懂得,为什么我不想重装。
(安装Win7必须是原装光驱在光驱位)

以前是300G的一块硬盘,后来加了500G的SSD(SSD在硬盘位,原装硬盘在光驱位),在SSD上安装了MAC和Win7。

但最近,MAC盘彻底满了,而Win7的系统盘还有不少空间,于是准备调整一下Win7系统盘的大小。

首先Win7安装了Ghost15,做了个备份,是v2i格式的。

然后重启到MAC系统,删掉Win7分区,用Bootcamp向导平分了整个SSD。

关机,将SSD拿下来,放到移动硬盘盒里,连到另一台笔记本上,准备Ghost回来。

靠,Ghost了两次,都失败了。。。

心里哇凉哇凉的啊。

放回MAC里发现,文件的确可以看得见,但明显不对啊,250G空间,用了200G,还有 150G。

靠,坑爹啊,Windows干脆不认。。。

估计是直接按原来的硬盘分区恢复的,现在硬盘分区变小了,当然放不下,但Ghost大哥,你好歹提示一下啊,欲哭无泪
(如果先把Win7分区缩小,再备份,再还原,应该就可以了)

现在没招了,直接文件恢复吧

直接将v2i备份中的全部文件,还原到新的分区,测试了一下,认不到Win7。

实在不想把光驱恢复,于是想了下,用VMWare,建了个虚拟机,连上移动硬盘,光盘启动。

进入Win7修复界面,

bootrec /FixMbr
...OK

bootrec /FixBoot
...找不到元素

这算啥啊,网上找了下,用diskpart命令将Win7分区设为Active。

bootrec /FixBoot
...ok

bootrec /RebuildBcd
...找不到设备

bcdedit /export C:\bcdbackup
...找不到设备

我靠,你都能看到C盘,你告诉我找不到设备

直接修复启动,还是不行。

疯了。

最后一搏,不用虚拟机,直接将原装光驱换上,光盘启动,修复。
直接提示启动项有问题
修复后重启,好了。

进入系统后,office2010报告无法安装字体文件,直接修复安装,OK。

原装硬盘以前划分了部分空间给MAC,先在MAC系统下数据备份出来,删除分区。
到Windows下,直接扩展了分区。
到MAC下,用gdisk,调整了GPT的分区表。
终于搞定了!

结果,周末没陪老婆,被骂了。。。
哄老婆去了。。。

PS:
1、用老毛桃的PE,换了多个版本,U盘版本无法启动,硬盘版本启动后,找不到设备
2、用一键Ghost,也很挫,硬盘版启动后认不到U盘,U盘版本无法启动
3、其实,虚拟机里,提示过Win7启动项有问题,但我忽略了,否则有可能不需要换光驱
4、下一次可以试一下,直接用虚拟机备份还原,应该前面两个工具就都能用了

此外:
1、Win7驱动有问题,连接移动硬盘后,经常被认成键盘鼠标,移除后就只能强制关机了
2、不知道什么原因,使用iPhone耳机连接后,只有一个声道的声音,而用小米的耳机就有两个声道,不知道哪里的原因,好烦