发现MongoDB特别适合自动化检测数据的存储。。。
例如一个晶圆检测项目,定义其数据结构如下
#pragma once
#include <vector>
#include <QString>
#include <QRectF>
#include <string>
#include <memory>
class tpoWafer;
class tpoDie;
class tpoDefect;
class tpoWafer
{
public:
std::vector<std::shared_ptr<tpoDie>>Layouts; //晶圆的layout
QRectF MaskArea;
QString WaferID;
QString BatchID;
QString ProductID;
QString StepID;
QString LotID;
QString EqpID;
QString UnitID;
QString OperatorID;
QString RecipeName;
QString RecipeID;
int TotalDie;
int OKDie;
int NGDie;
int TotalDefect;
double Mark_x;
double Mark_y;
QString Judge;
QString WarningLevel;
int WariningCode;
QString StartTime;
QString EndTime;
int ImageCount;
QString ImagePath;
};
class tpoDie
{
public:
std::vector<std::shared_ptr<tpoDefect>>InspectedDefect; //检测到的缺陷
double die_x;
double die_y;
double die_width;
double die_height;
double die_type;
int die_model;
};
class tpoDefect
{
public:
int id = -1;
double x = 0;
double y = 0;
double gray = 0;
double height = 0;
double width = 0;
double size = 0;
double roundness = 1;
int type = -1;
int judge = 0;
QRectF bounding = QRectF(0, 0, 1, 1);
bool visible = true;
bool skip = false;
int inspect_type = 1;
int flag = -1;
};
如果用的是结构型数据库存储数据,就需要在数据库中建立3个表,wafer table,die table defect table,还要用外键进行关联。
而在MongoDB这类非关系型数据库中这些都不需要,只需按照定义的数据结构把数据写成类似json文件的domcument存到数据中就可以了。最最重要的是,当数据结构改变了,增加或者减少存储的数据时完全不需要改数据库表,这个在关系型数据库中就不行了。
bool tpoWafer::write_to_database(bsoncxx::builder::stream::document& doc)
{
int idx = 0;
doc <<
"MaskArea_x" + std::to_string(idx) << MaskArea.x() <<
"MaskArea_y" + std::to_string(idx) << MaskArea.y() <<
"MaskArea_width" + std::to_string(idx) << MaskArea.width() <<
"MaskArea_height" + std::to_string(idx) << MaskArea.height() <<
"WaferID" + std::to_string(idx) << WaferID.toStdString() <<
"BatchID" + std::to_string(idx) << BatchID.toStdString() <<
"ProductID" + std::to_string(idx) << ProductID.toStdString() <<
"StepID" + std::to_string(idx) << StepID.toStdString() <<
"LotID" + std::to_string(idx) << LotID.toStdString() <<
"EqpID" + std::to_string(idx) << EqpID.toStdString() <<
"UnitID" + std::to_string(idx) << UnitID.toStdString() <<
"OperatorID" + std::to_string(idx) << OperatorID.toStdString() <<
"RecipeName" + std::to_string(idx) << RecipeName.toStdString() <<
"RecipeID" + std::to_string(idx) << RecipeID.toStdString() <<
"TotalDie" + std::to_string(idx) << TotalDie <<
"OKDie" + std::to_string(idx) << OKDie <<
"NGDie" + std::to_string(idx) << NGDie <<
"TotalDefect" + std::to_string(idx) << TotalDefect <<
"Mark_x" + std::to_string(idx) << Mark_x <<
"Mark_y" + std::to_string(idx) << Mark_y <<
"Judge" << Judge.toStdString() <<
"WarningLevel" + std::to_string(idx) << WarningLevel.toStdString() <<
"WariningCode" + std::to_string(idx) << WariningCode <<
"StartTime" + std::to_string(idx) << StartTime.toStdString() <<
"EndTime" + std::to_string(idx) << EndTime.toStdString() <<
"ImageCount" + std::to_string(idx) << ImageCount <<
"ImagePath" + std::to_string(idx) << ImagePath.toStdString();
for (int i = 0; i < Layouts.size(); i++)
{
Layouts[i]->write_to_database(doc, i);
}
return true;
}
bool tpoDefect::write_to_database(bsoncxx::builder::stream::document& doc, int idx)
{
doc << "defect_info"+ std::to_string(idx) << bsoncxx::builder::stream::open_document <<
"id"+ std::to_string(idx) << id <<
"x" + std::to_string(idx) << x <<
"t" + std::to_string(idx) << y <<
"gray" + std::to_string(idx) << gray <<
"height" + std::to_string(idx) << height <<
"width" + std::to_string(idx) << width <<
"size" + std::to_string(idx) << size <<
"roundness" + std::to_string(idx) << roundness <<
"type" + std::to_string(idx) << type <<
"judge" + std::to_string(idx) << judge <<
"bounding_x" + std::to_string(idx) << bounding.x() <<
"bounding_y" + std::to_string(idx) << bounding.y() <<
"bounding_width" + std::to_string(idx) << bounding.width() <<
"bounding_height" + std::to_string(idx) << bounding.height() <<
"visible" + std::to_string(idx) << visible <<
"skip" + std::to_string(idx) << skip <<
"inspect_type" + std::to_string(idx) << inspect_type <<
"flag" << flag;
doc << bsoncxx::builder::stream::close_document;
return false;
}
bool tpoDie::write_to_database(bsoncxx::builder::stream::document& doc, int idx)
{
doc << "die_info" + std::to_string(idx) <<bsoncxx::builder::stream::open_document<<
"die_x" + std::to_string(idx) << die_x <<
"die_y" + std::to_string(idx) << die_y <<
"die_width" + std::to_string(idx) << die_width <<
"die_height" + std::to_string(idx) << die_height <<
"die_type" + std::to_string(idx) << die_type <<
"die_model" + std::to_string(idx) << die_model <<
"die_id" + std::to_string(idx) << die_id.toStdString();
for (int i = 0; i < InspectedDefect.size(); i++)
{
InspectedDefect[i]->write_to_database(doc, i);
}
doc << bsoncxx::builder::stream::close_document;
return true;
}
对每个数据结构写一个write document的方法,最后只需要调用wafer的write_to_database方法就能把wafer的每个die的详细信息记录到表中,包括每个die中的缺陷详细信息。
写到数据库中的数据结构是这样的,结构一目了然,wafer中带着die的信息和自身的一些详细信息,die中又有defect的详细信息。
而且这个数据库查询效率奇高,实测千万级的数据,添加了索引之后能在0.1秒之内查询到结果。