GetMatch

template < typename STATE >
int ExtRanker_T<STATE>::GetMatches ()
{
	if ( !m_pRoot )
		return 0;

	int iMatches = 0;
	const ExtHit_t * pHlist = m_pHitlist;
	const ExtDoc_t * pDocs = m_pDoclist;

	// warmup if necessary
	if ( !pHlist )
	{
		if ( !pDocs ) pDocs = GetFilteredDocs ();
		if ( !pDocs ) return iMatches;

		pHlist = m_pRoot->GetHitsChunk ( pDocs, m_uMaxID );
		if ( !pHlist ) return iMatches;
	}

	// main matching loop
	const ExtDoc_t * pDoc = pDocs;
	for ( SphDocID_t uCurDocid=0; iMatches<ExtNode_i::MAX_DOCS; )
	{
		// keep ranking
		while ( pHlist->m_uDocid==uCurDocid )
			//计算
		 	m_tState.Update ( pHlist++ );

		// if hits block is over, get next block, but do *not* flush current doc
		if ( pHlist->m_uDocid==DOCID_MAX )
		{
			assert ( pDocs );
			pHlist = m_pRoot->GetHitsChunk ( pDocs, m_uMaxID );
			if ( pHlist )
				continue;
		}

		// otherwise (new match or no next hits block), flush current doc
		if ( uCurDocid )
		{
			assert ( uCurDocid==pDoc->m_uDocid );
			Swap ( m_dMatches[iMatches], m_dMyMatches[pDoc-m_dMyDocs] );
			m_dMatches[iMatches].m_iWeight = m_tState.Finalize ( m_dMatches[iMatches] );
			iMatches++;
		}

		// boundary checks
		if ( !pHlist )
		{
			// there are no more hits for current docs block; do we have a next one?
			assert ( pDocs );
			pDoc = pDocs = GetFilteredDocs ();

			// we don't, so bail out
			if ( !pDocs )
				break;

			// we do, get some hits
			pHlist = m_pRoot->GetHitsChunk ( pDocs, m_uMaxID );
			assert ( pHlist ); // fresh docs block, must have hits
		}

		// skip until next good doc/hit pair
		assert ( pDoc->m_uDocid<=pHlist->m_uDocid );
		while ( pDoc->m_uDocid<pHlist->m_uDocid ) pDoc++;
		assert ( pDoc->m_uDocid==pHlist->m_uDocid );

		uCurDocid = pHlist->m_uDocid;
	}

	m_pDoclist = pDocs;
	m_pHitlist = pHlist;
	return iMatches;
}

通过下边这段代码可以发现;

		while ( pHlist->m_uDocid==uCurDocid )
			//计算
		 	m_tState.Update ( pHlist++ );
如果pHlist指针指向的ExtHit_t结构的id,是这个id,就一直调用Update函数,来填充m_tState的数据,他最终存储的是一个id的综合评分。

/// hit in the stream
struct ExtHit_t
{
	SphDocID_t	m_uDocid;
	Hitpos_t	m_uHitpos;
	WORD		m_uQuerypos;
	WORD		m_uNodepos;
	WORD		m_uSpanlen;
	WORD		m_uMatchlen;
	DWORD		m_uWeight;
};
ExtHit_t的结构如上,m_uDocid存储id信息。而m_uHitpos字段存储了很多信息,哪个字段,是否结束,位置,以及最长公共子串。

字段值最大是多少呢?

if ( m_uCurLCS>m_uLCS[uField] )
			m_uLCS[uField] = m_uCurLCS;

BYTE m_uLCS[SPH_MAX_FIELDS];

#define SPH_MAX_FIELDS			256
可以发现最大值是256.而字段值就存储在m_uHitpos最前面的8位,最小为0,最大为256。
	static inline DWORD GetLCS ( Hitpos_t uHitpos )
	{
		//1左移23位取反与uHitpos进行与操作
		return uHitpos & ~FIELDEND_MASK;
	}
正数的补码是其本身,负数的补码是除符号位取反加1。

此处一定要区分反码与取反的区别:

1的反码还是1

1按位取反,11111....1110,而计算机在存储的时候是补码存储的,-2的补码刚好是这个,所以1按位取反是-2.

同样,00000000 10000000 00000000 00000000
取反,11111111 01111111 11111111 11111111

减1,  11111111 01111111 11111111 11111110

除符号位取反

             10000000  10000000 00000000 00000001

所以他的反码是-8388609


这是数据举例

indextool -c ../etc/csft_daquan_suggest_all.conf --dumphitlist csft_daquan_suggest_web dai

通过indextool工具查看索引的情况,可以看到索引的内容,此语句查找命中dai的doc和hit

doc=500163049, hit=0x00800001
doc=500163049, hit=0x01800001

mysql> select * from IBO_suggest_info_web where id=500163049 \G;
*************************** 1. row ***************************
               id: 500163049
             type: 5
            title: Daisy
           weight: 2012583
           pinyin: Daisy
   is_web_removed: 1
is_client_removed: 1

在上边介绍的图中可以发现0x00800001的前8位,即00表示命中的字段,在此例中有00和01,

在上边数据库数据中也可以发现,title和pinyin中都有dai的数据。

0x00800001中的80,则表示在字段开头或结尾时命中。

后16位为,0001,表示title分词的第一个命中,

下边再举一例

doc=117884, hit=0x00800002

mysql> select * from IBO_suggest_info_web where id=117884 \G;
*************************** 1. row ***************************
               id: 117884
             type: 0
            title: 茫然一代
           weight: 1976000
           pinyin: mangranyidai
   is_web_removed: 1
is_client_removed: 1

可以用messg查看分词情况:

茫然/x 一代/x 

一代在分词的第二个位置,并且是后边没内容了,所以80,后边为02。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值