SQL Server DBのvarbinary(max)
列にフルテキストインデックスを設定しました。 type列が指定されており、「。doc」、「。pdf」などのファイルの拡張子が含まれています。
ただし、.rtfファイルにインデックスが付けられている場合、SQLはすべてのメタ情報(RTFタグ "listoverridecount0"など)をファイルに含めていることに気付きました。
これはインデックスをかなり膨らませており、検索がこれらのタグで一致することも意味します(つまり、「listoverridecount0」で検索して、すべての.rtfを返すことができます)。
.rtfのiFilterがRTFタグを削除しないのはなぜですか?
これを実行すると:
SELECT * FROM sys.fulltext_document_types WHERE document_type = '.rtf';
私はこれを手に入れます:
document_type .rtf
class_id C7310720-AC80-11D1-8DF3-00C04FB6EF4F
path c:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Binn\msfte.dll
version 12.0.6828.0
manufacturer Microsoft Corporation
Microsoft Connectバグ を提出しました。回避策を見つけることができないようです。おそらくこれは、a)RTF iFilterがタグを削除しないことによるエラー、またはb)全文索引の問題のいずれかです。
私のSQL Serverのバージョンは次のとおりです。
Microsoft SQL Server 2012(SP1)-11.0.3393.0(X64) 2013年10月25日19:04:40 著作権(c)Microsoft Corporation Developer Edition(64ビット) Windows NT 6.2(ビルド9200:)(ハイパーバイザー)
これは再現できますが、いくつかの選択肢があると思います。
-- Convert rtf to plain text
SELECT
CAST( file_stream AS VARCHAR(MAX) ) original
, MDS.mdq.RegExReplace(
CAST( file_stream AS VARCHAR(MAX) ),
'\{\*?\\[^{}]+}|[{}]|\\\n?[A-Za-z]+\n?(?:-?\d+)?[ ]?', '', 1 )
FROM dbo.Documents
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Text;
using System.Linq; // for TakeWhile
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlChars rtfToText( SqlChars inputRtf )
{
// RTF function lifted from here and adapted for SQL CLR:
// https://stackoverflow.com/questions/23277178/richtextbox-throws-outofmemory-on-Azure
bool slash = false; //indicates if backslash followed by the space
bool figure_opened = false; //indicates if opening figure brace followed by the space
bool figure_closed = false; //indicates if closing brace followed by the space
bool first_space = false; //the else spaces are in plain text and must be included to the result
if (inputRtf.Length < 4) return new SqlChars ( string.Empty );
int i = 0;
i = inputRtf.ToString().IndexOf("\\pard");
if (i < 1) return new SqlChars(string.Empty);
var builder = new StringBuilder();
for (int j = i; j < inputRtf.Length - 1; j++)
{
char ch = inputRtf[j];
char nextCh = inputRtf[j + 1];
if (ch == '\\' && nextCh == 'p') // appends \n if \pard, except for first
{
if (j > i && j < inputRtf.Length - 4)
{
string fiveChars = inputRtf.ToString().Substring(j, 5);
if (fiveChars.Equals("\\pard"))
{
builder.Append("\n");
}
}
}
if (ch == '\\' && nextCh == 'u') // to deal correctly with special characters
{
string fourChars = inputRtf.ToString().Substring(j + 2, 4);
string digits = new string(fourChars.TakeWhile(char.IsDigit).ToArray());
char specialChar = (char)int.Parse(digits);
builder.Append(specialChar);
j += digits.Length + 5;
continue;
}
if (ch == '\\' && nextCh == '{') // if the text contains symbol '{'
{
slash = false;
figure_opened = false;
figure_closed = false;
first_space = false;
builder.Append('{');
j++;
continue;
}
else if (ch == '\\' && nextCh == '}') // if the text contains symbol '}'
{
slash = false;
figure_opened = false;
figure_closed = false;
first_space = false;
builder.Append('}');
j++;
continue;
}
else if (ch == '\\' && nextCh == '\\') // if the text contains symbol '\'
{
slash = false;
figure_opened = false;
figure_closed = false;
first_space = false;
builder.Append('\\');
j++;
continue;
}
else if (ch == '\\') // we are looking at the backslash
{
first_space = true;
slash = true;
}
else if (ch == '{')
{
first_space = true;
figure_opened = true;
}
else if (ch == '}')
{
first_space = true;
figure_closed = true;
}
else if (ch == ' ')
{
slash = false;
figure_opened = false;
figure_closed = false;
}
if (!slash && !figure_opened && !figure_closed)
{
if (!first_space)
{
builder.Append(ch);
}
else
{
first_space = false;
}
}
}
// Return
return new SqlChars(builder.ToString());
}
};
これは世界で最も効率的なCLR関数ではないと確信していますが、テストした約100のドキュメントで問題なく機能しましたが、いくつかの失敗がありました。
接続アイテムについて何か聞こえた場合はお知らせください。
使用しているMSSQLのバージョンはわかりませんが、このリンクは役に立ちますか? SQL Filters SQL Server内で設定されているさまざまなフィルターを調べます。rtfフィルターが正しく読み込まれていない可能性がありますか?