MongoDB在自动化设备上的应用示例

时间:2024-12-13 07:07:12

发现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秒之内查询到结果。