CSphSource 数据源
CSphSource_XMLPipe2-XML文件获取数据
CSphSource_SQL-SQL(MySQL)获取数据
CSphIndex 索引器
派生类CSphIndex_VLN
// 索引过程
virtual int Build ( CSphDict * pDict,
const CSphVector & dSources, // 所有数据源
int iMemoryLimit, // 内存设置
ESphDocinfo eDocinfo );
/// available docinfo storage strategies
enum ESphDocinfo
{
SPH_DOCINFO_NONE = 0, ///< no docinfo available
SPH_DOCINFO_INLINE = 1, ///< inline docinfo into index (specifically, into doclists)
SPH_DOCINFO_EXTERN = 2 ///< store docinfo separately
};
BYTE ** CSphSource_SQL::NextDocument ( CSphString & sError )
{
m_tDocInfo.m_iDocID = sphToDocid ( SqlColumn(0) ); // 取得文档ID值
}
bool CSphSource_Document::IterateHitsNext ( CSphString & sError )
{
while ( ( sWord = m_pTokenizer->GetToken() )!=NULL ) //分词
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CSphAutofile fdTmpDocinfos (“tmp2″) // 存储文档信息
DOCINFO2ID(pDocinfo) = pSource->m_tDocInfo.m_iDocID; // 自定义ID
memcpy ( DOCINFO2ATTRS(pDocinfo), pSource->m_tDocInfo.m_pRowitems, sizeof(CSphRowitem)*m_tSchema.GetRowSize() );
pDocinfo += iDocinfoStride;
Sphinx使用的文件包括 “sph”, “spa”, “spi”, “spd”, “spp”, “spm” ,还有锁文件。其中sph是系统的配置文件。其它则为索引文件。
.Spi 文件:保存WordId及指向此WordId对应的文档信息在spd文件的指针。Spi文件在检索程序启动时完全加载入内存。Spi文件是分块的,块内排序,块之间也排序。分块的目的应该是为了快速检索到WordId,因为Spi中的WordId是变长压缩的,索引需要先在块级别做二分定位,再在快内解压缩查找。
文件结构,每块中结构,wordId实际存储的是差值
WordId | SpdFilePointer | DocNum | HitNum
.Spd文件:文件结构
DocID | [DocInfo] | HitFilePointer | FieldNum | HitNum
.Spp文件: 文件结构
HitPos
.Spa文件:存储DocInfo的文件,检索程序启动时会把此文件加载如内存,sphinx可以指定DocInfo的存储方式,
① 存储到spd文件中(InLine)
②. 另外单独存储。指定此,就会生成spa文件
文件结构:
DocId | DocInfo
.Spm文件:在DocInfo中,有一种特殊的属性,叫MVA,多值属性。Sphinx对此属性特殊处理,需要存储在spm文件中。检索程序启动时会把此文件加载如内存。此(MVA)属性在DocInfo对应位置存储其在此文件中的字节偏移量。
文件结构:
DocId | Anum,A1,A2,…,An | Bnum,B1,B2,…,Bn | …
由于在第一趟扫描过程中会出现WordID相同的不同Hits(不同文档或者不同位置不同字段),二趟前会根据WordID排序,WordID相同的Hits会连续出现并合并(合并到第一次出现的相同WordID中)
/////////////////////////////////////////////
Spi文件
// 遍历所有的数据源
// 遍历所有的文档
struct CSphWordHit
{
SphDocID_t m_iDocID; ///< document ID
SphWordID_t m_iWordID; ///< word ID in current dictionary
DWORD m_iWordPos; ///< word position in current document
};
CSphWordHit.. CSphWordHit…CSphWordHit…CSphWordHit串接
dHitBlocks.Add( cidxWriteRawVLB ( fdTmpHits.GetFD(), dHits, iHits, NULL, 0, 0 ) );//
GetIndexFileName(“tmp1″) 将Hits流写入tmp1文件。临时文件
不论重复,不论字段
dBins->ReadHit(&tHit,iRowitems,dInlineAttrs+i*iRowitems )// 重新读入内存
cidxHit(tQueue.m_pData,iRowitems?dInlineAttrs+iBin*iRowitems : NULL );
// 统计后刷入m_wrWordlist,形如以下字节流(有缓冲,缓冲满则写入磁盘)
WordId | SpdFilePointer | DocNum | HitNum
此时写入的是最终的索引文件,格式如上
Spd文件
文件结构
DocID | [DocInfo] | HitFilePointer | FieldNum | HitNum
//tQuery.m_eMode = SPH_MATCH_ANY;
tQuery.m_eMode = SPH_MATCH_BOOLEAN;
//tQuery.m_eMode = SPH_MATCH_PHRASE;
//tQuery.m_eMode = SPH_MATCH_EXTENDED;
//tQuery.m_eMode = SPH_MATCH_EXTENDED2;
//SPH_SORT_RELEVANCE 模式, 按相关度降序排列(最好的匹配排在最前面)
//SPH_SORT_ATTR_DESC 模式, 按属性降序排列(属性值越大的越是排在前面)
//SPH_SORT_ATTR_ASC模式, 按属性升序排列(属性值越小的越是排在前面)
//SPH_SORT_TIME_SEGMENTS 模式, 先按时间段(最近一小时/天/周/月)降序,再按
// 相关度降序
//SPH_SORT_EXTENDED 模式, 按一种类似SQL的方式将列组合起来,升序或降序排
// 列。
//SPH_SORT_EXPR 模式,按某个算术表达式排序。
switch ( pQuery->m_eMode )
{
case SPH_MATCH_ALL: bMatch = MatchAll ( pQuery, pResult, iSorters, ppSorters ); break;// 与查询
case SPH_MATCH_PHRASE: bMatch = MatchAll ( pQuery, pResult, iSorters, ppSorters ); break;//短语查询
case SPH_MATCH_ANY: bMatch = MatchAny ( pQuery, pResult, iSorters, ppSorters ); break; //或查询
case SPH_MATCH_BOOLEAN: bMatch = MatchBoolean ( pQuery, pResult, iSorters, ppSorters, tTermSetup ); break;//布尔查询
case SPH_MATCH_EXTENDED: bMatch = MatchExtendedV1 ( pQuery, pResult, iSorters, ppSorters, tTermSetup ); break;//扩展查询
case SPH_MATCH_EXTENDED2: bMatch = MatchExtended ( pQuery, pResult, iSorters, ppSorters, tTermSetup ); break;
case SPH_MATCH_FULLSCAN: bMatch = MatchFullScan ( pQuery, iSorters, ppSorters, tTermSetup ); break;
default: sphDie ( “INTERNAL ERROR: unknown matching mode (mode=%d)”, pQuery->m_eMode );
}
ISphTokenizer * pTokenizer
// 用作解析的配置信息,例如字符集,切词规则(n-gram)
// 包括同义词,过滤词
1. pResult = pIndex->Query ( pTokenizer, pDict, &tQuery );
{
ISphMatchSorter * pTop = sphCreateQueue ( pQuery, m_tSchema, sError );(
pTop=newCSphMatchQueue<matchrelevancelt_fn> ( pQuery->m_iMaxMatches, bUsesAttrs ); //选择排序规则
)
2. if ( QueryEx ( pTokenizer, pDict, pQuery, pResult, pTop ) )
3. bool bRes = MultiQuery ( pTokenizer, pDict, pQuery, pResult, 1, &pTop );
4. case SPH_MATCH_BOOLEAN: bMatch = MatchBoolean ( pQuery, pResult, iSorters, ppSorters, tTermSetup );