Java
mecab
oracle
形態素解析
ログ解析

DBに入れたログを形態素解析してDBに入れてメッセージ分類したい1


JavaPG

dbに格納されたログメッセージをGROPUP化して更にMecabで形態素解析して正規化するPGを作った


Tiggercmd.java

import java.io.File;

import java.io.FileInputStream;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

import oracle.jdbc.*;
import net.moraleboost.mecab.Lattice;
import net.moraleboost.mecab.impl.StandardTagger;
import net.moraleboost.mecab.Node;
class Tiggercmd {
static String[] hinsis = {
"type0","type1","type2","type3","style0","style1","calls0","calls1","calls2"
};
public static void main(String[] args) throws Exception { // Taggerを構築。
if (args.length<1) {
System.err.println(
"USAGE:Tiggercmd readwrite-propfileName(non extents)"
);
return;
}
StandardTagger tagger = new StandardTagger("");
// バージョン文字列を取得
System.err.println("MeCab version " + tagger.version());
// Lattice(形態素解析に必要な実行時情報が格納されるオブジェクト)を構築
Lattice lattice = tagger.createLattice();
//INFOプロパティを開く
Properties Tiggercmd_props = new Properties();
Tiggercmd_props.load(new FileInputStream(new File(args[0])));
OracleConnection con1 = null;
OracleConnection con2 = null;
PreparedStatement in_sql_prepare = null;
ResultSet in_rls = null;
OraclePreparedStatement con2prpares = null;
int msgid = 0;
int seq =0;
String features[] = null;
try {
//IN DBへコネクト
con1 = connect(Tiggercmd_props.getProperty("conids1.user"), Tiggercmd_props.getProperty("conids1.password"),Tiggercmd_props.getProperty("conids1.TNSPINGString"));
//WRITE DBへコネクト
con2 = connect(Tiggercmd_props.getProperty("conids2.user"), Tiggercmd_props.getProperty("conids2.password"),Tiggercmd_props.getProperty("conids2.TNSPINGString"));
//readQuery実行
in_sql_prepare = con1.prepareStatement(Tiggercmd_props.getProperty("in.sqls"));
in_rls = in_sql_prepare.executeQuery();
System.err.println("READSQL:"+in_sql_prepare.toString());
while (in_rls.next() ){
// 解析対象文字列をセット
String in_surface = in_rls.getString(Tiggercmd_props.getProperty("in.surface_colname"));//String text = "本日は晴天なり。";
System.out.println(msgid+":\t"+in_surface);
lattice.setSentence(in_surface);
tagger.parse(lattice);
// 形態素解析結果を出力
System.out.println(lattice.toString());
// 一つずつ形態素をたどりながら、表層形と素性を出力
Node node = lattice.bosNode();
while (node != null) {
String addssql = Tiggercmd_props.getProperty("wr.sqls");
//OraclePreparedStatementで解析変数にセットしてゆく
con2prpares = (OraclePreparedStatement)con2.prepareStatement(addssql);
con2prpares.setIntAtName("msgid",msgid);
con2prpares.setStringAtName("msg",in_surface);
con2prpares.setIntAtName("seq",seq);
con2prpares.setStringAtName("surface",node.surface());
con2prpares.setStringAtName("feature",node.feature());
features = node.feature().split(",");
for (int i=0;i<hinsis.length;i++){
con2prpares.setStringAtName(hinsis[i],(i<features.length)?features[i]:null);
}
//更新と更新数の出力
System.err.println("inserts:\t"+con2prpares.executeUpdate());
con2prpares.close();con2prpares=null;
node = node.next();
seq++;
}
con2.commit();
seq = 0;
lattice.clear();
msgid ++;
}
in_rls.close();in_rls=null;
in_sql_prepare.close();in_sql_prepare=null;
con1.close();con1=null;
con2.close();con2=null;
}catch (Exception oe){
oe.printStackTrace(System.err);
}finally {
try {
if (in_rls!=null) in_rls.close();
if (in_sql_prepare!=null) in_sql_prepare.close();
if (con1 != null) con1.close();
if (con2prpares!=null) con2prpares.close();
if (con2 != null) con2.close();
}catch (Exception fe){}
}
// lattice, taggerを破壊
lattice.destroy();
tagger.destroy();
}
/**
* Utility method: creates a new JDBC connection to the database.
*/

static OracleConnection connect(String user,String password,String tnspingString) throws Exception {
OracleConnection conn = null;
OracleDriver dr = new OracleDriver();
Properties prop = new Properties();
prop.setProperty("user",user);
prop.setProperty("password",password);
conn = (OracleConnection)dr.connect("jdbc:oracle:thin:@"+tnspingString,prop);
conn.setAutoCommit(false);
return conn;
}
}



properties


domainlogconrwinfo.properties

#INFO

#クエリ対象接続情報
conids1.user=hoge
conids1.password=hoge
conids1.TNSPINGString=(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.XXX)(PORT = 1521))) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = servicename1)))
#↑tnspings 接続名 で出力されたフル接続情報を記載

#INSERT対象接続情報
conids2.user=hoge
conids2.password=hoge
conids2.TNSPINGString=(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.***)(PORT = 1521))) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = servicenamea)))
#↑tnspings 接続名 で出力されたフル接続情報を記載

in.sqls= \
select a.MESSAGETEXT,count(a.TIMEPARTS) from domainlog a \
where 1=1 \
group by a.MESSAGETEXT \
order by a.MESSAGETEXT

#↑解析したいメッセージ一覧を取得するSQL
in.surface_colname=MESSAGETEXT
#↑そのSQLでメッセージにあてられたカラム名

#↓INSERTのSQL
wr.sqls= \
insert into domainlog_rexs (msgid,MESSAGETEXT,seq,surface,manals \
,type0,type1,type2,type3,style0,style1,calls0,calls1,calls2 ) \
values(:msgid,:msg,:seq,:surface,:feature, \
:type0,:type1,:type2,:type3,:style0,:style1,:calls0,:calls1,:calls2 \
)

#↑以下の形態素解析データ変数をカラムに合わせてVALUES内に記載するとそこに以下変数が設定さる
#:msgid 解析メッセージの通番
#:msg 解析メッセージの文字列
#:seq 解析形態素の通番
#:surface 解析形態素の表層文字列
#:feature 素性(品詞?)体系解析結果文字列
#:type0 IPA Type1
#:type1 IPA Type2
#:type2 IPA Type3
#:type3 IPA Type4
#:style0 型1
#:style1 型2
#:calls0 読み1
#:calls1 読み2
#:calls2 読み3
#参考リンク https://qiita.com/priancho/items/f633a9e99616b3fe451f



そして正規化の為に読み1を使って同じ言い回しを一覧で表示し名詞を部品として表示。

文字のサマリはLISTAGG (文字のSUMカタログ関数)を使う

SQL:

--MSGID,MSGTEXT毎の解析結果でCALLS1を結合した一覧を出す

select a.MESSAGETEXT,a.MSGID,a.CONCATHINSIWORD,a.ITEMS from (

select a.MSGID,a.MESSAGETEXT,b.ITEMS

,listagg(a.CALLS1,';') within group (order by a.MSGID,a.SEQ) as concatHINSIWORD

from domainlog_rexs a

,(select a.MSGID,listagg(a.SURFACE,';') within group (order by a.SEQ) as items

from domainlog_rexs a

where 1=1

and a.SURFACE is not null

and a.TYPE0='名詞'

and a.TYPE1 in (

'一般'

,'数'

,'サ変接続'

)

group by a.MSGID) b

where 1=1

and ( a.CALLS0 <> '*' and a.TYPE0 is not null)

and a.MSGID=b.MSGID

group by a.MSGID,a.MESSAGETEXT,b.ITEMS

) a

order by a.MSGID


表示結果例

mecab.png


正規化の結果と日本のソフトウエアエンジニア界隈への危惧

結果:

1万行程のログメッセージが単純メッセージのグループ化で数千程に減り、

更にこの形態素解析結果の言い回しでのグループ化により百パター以下に減りました。

結果的に人が目を配る対象数は何分の1になったでしょうか?

危惧:

こういった研究者が生み出した有用な知恵(今回例は形態素解析エンジンMecab)を

流行に流されずに取り込み実用的にしている

日本のベンダーや有名ソフトハード開発製造販売会社は居るのでしょうか?

その理由は既存利益構造を変える事が自分達には最も危険な行動だからでは?

これをブレーク出来なければ東京オリンピック迄にどうなるのか?

日本人エンジニアとして危惧しております。


以上