XSIndex

XS
繼承關系 class XSIndex » XSServer » XSComponent
版本 1.0.0
源代碼 sdk/php/lib/XSIndex.class.php
XS 索引管理 添加/刪除/修改索引數據

Public 屬性

隱去繼承來的屬性

名稱類型描述定義于
connString string 連接字符串 XSServer
customDict string 獲取自定義詞典內容 XSIndex
project string 獲取當前項目名稱 XSServer
respond XSCommand 從服務器讀取響應指令 XSServer
scwsMulti int 獲取當前索引庫的分詞復合等級 XSIndex
socket mixed 獲取連接資源描述符 XSServer
xs XS 服務端關聯的 XS 對象 XSServer

Protected 屬性

隱去繼承來的屬性

名稱類型描述定義于
_conn XSServer
_flag XSServer
_project XSServer
_sendBuffer XSServer
_sock XSServer

Public 方法

隱去繼承來的方法

名稱描述定義于
__construct() 構造函數, 打開連接 XSServer
__destruct() 析構函數 XSIndex
__get() 魔術方法 __get XSComponent
__isset() 魔術方法 __isset XSComponent
__set() 魔術方法 __set XSComponent
__unset() 魔術方法 __unset XSComponent
add() 添加文檔到索引中 XSIndex
addExdata() 批量提交索引命令封包數據 XSIndex
addServer() 增加一個同步索引服務器 XSIndex
addSynonym() 添加同義詞 XSIndex
beginRebuild() 開始重建索引 XSIndex
clean() 完全清空索引數據 XSIndex
close() 關閉索引服務端連接 XSIndex
closeBuffer() 提交所有指令并關閉緩沖區 XSIndex
del() 刪除索引中的數據 XSIndex
delSynonym() 刪除某個同義詞 XSIndex
endRebuild() 完成并關閉重建索引 XSIndex
execCommand() 執行服務端指令并獲取返回值 XSIndex
flushIndex() 強制刷新服務端的當前庫的索引緩存 XSIndex
flushLogging() 強制刷新服務端當前項目的搜索日志 XSIndex
getConnString() Returns 連接字符串 XSServer
getCustomDict() 獲取自定義詞典內容 XSIndex
getProject() 獲取當前項目名稱 XSServer
getRespond() 從服務器讀取響應指令 XSServer
getScwsMulti() 獲取當前索引庫的分詞復合等級 XSIndex
getSocket() 獲取連接資源描述符 XSServer
hasRespond() 判斷服務端是否有可讀數據 XSServer
open() 打開服務端連接 XSServer
openBuffer() 開啟索引命令提交緩沖區 XSIndex
reopen() 重新打開連接 XSServer
sendCommand() 往服務器直接發送指令 (無緩存) XSServer
setCustomDict() 設置自定義詞典內容 XSIndex
setDb() 更改存放索引數據的目錄 XSIndex
setProject() 設置當前項目 XSServer
setScwsMulti() 設置當前索引庫的分詞復合等級 XSIndex
setTimeout() 設置服務端超時秒數 XSServer
stopRebuild() 中止索引重建 XSIndex
update() 更新索引文檔 XSIndex

Protected 方法

隱去繼承來的方法

名稱描述定義于
check() 檢測服務端的連接情況 XSServer
connect() 連接服務端 XSServer
read() 讀取數據 XSServer
write() 寫入數據 XSServer

屬性明細

customDict 屬性
public string getCustomDict()
public void setCustomDict(string $content)

獲取自定義詞典內容

scwsMulti 屬性 (自版本 v1.4.7 起可用)
public int getScwsMulti()
public XSIndex setScwsMulti(int $level)

獲取當前索引庫的分詞復合等級

參見

方法明細

__destruct() 方法
public void __destruct()
源碼: sdk/php/lib/XSIndex.class.php#L528 (顯示)
public function __destruct()
{
    if (
$this->_rebuild === true) {
        try {
            
$this->endRebuild();
        } catch (
Exception $e) {
            
        }
    }
    foreach (
self::$_adds as $srv) {
        
$srv->close();
    }
    
self::$_adds = array();
    
parent::__destruct();
}

析構函數 在此自動關閉開啟的 rebuild

add() 方法
public XSIndex add(XSDocument $doc)
$doc XSDocument
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L72 (顯示)
public function add(XSDocument $doc)
{
    return 
$this->update($doctrue);
}

添加文檔到索引中 特別要注意的是: 系統不會自動檢測主鍵是否沖突, 即便已存在相同主鍵也會添加進去

參見

addExdata() 方法
public XSIndex addExdata(string $data, bool $check_file=true)
$data string 要提交的命令封包數據, 或存儲命令封包的文件路徑, 編碼必須已經是 UTF-8
$check_file bool 是否檢測參數為文件的情況
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L253 (顯示)
public function addExdata($data$check_file true)
{
    if (
strlen($data) < 255 && $check_file
            
&& file_exists($data) && ($data file_get_contents($data)) === false) {
        throw new 
XSException('Failed to read exdata from file');
    }

    
// try to check allowed (BUG: check the first cmd only):
    // XS_CMD_IMPORT_HEADER, XS_CMD_INDEX_REQUEST, XS_CMD_INDEX_REMOVE, XS_CMD_INDEX_EXDATA
    
$first ord(substr($data01));
    if (
$first != XS_CMD_IMPORT_HEADER
            
&& $first != XS_CMD_INDEX_REQUEST && $first != XS_CMD_INDEX_SYNONYMS
            
&& $first != XS_CMD_INDEX_REMOVE && $first != XS_CMD_INDEX_EXDATA) {
        throw new 
XSException('Invalid start command of exdata (CMD:' $first ')');
    }

    
// create cmd & execute it
    
$cmd = array('cmd' => XS_CMD_INDEX_EXDATA'buf' => $data);
    
$this->execCommand($cmdXS_CMD_OK_RQST_FINISHED);
    return 
$this;
}

批量提交索引命令封包數據 把多個命令封包內容連續保存為文件或變量, 然后一次性提交以減少網絡開銷提升性能

addServer() 方法
public XSServer addServer(string $conn)
$conn string 索引服務端連接參數
{return} XSServer
源碼: sdk/php/lib/XSIndex.class.php#L33 (顯示)
public function addServer($conn)
{
    
$srv = new XSServer($conn$this->xs);
    
self::$_adds[] = $srv;
    return 
$srv;
}

增加一個同步索引服務器

addSynonym() 方法 (自版本 v1.3.0 起可用)
public XSIndex addSynonym(string $raw, string $synonym)
$raw string 需要同義的原詞, 英文詞匯支持用空格分開多個單詞并強制被轉換為小寫
$synonym string 同義詞條, 最小語素, 勿帶空格等分隔符
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L283 (顯示)
public function addSynonym($raw$synonym)
{
    
$raw strval($raw);
    
$synonym strval($synonym);
    if (
$raw !== '' && $synonym !== '') {
        
$cmd = new XSCommand(XS_CMD_INDEX_SYNONYMSXS_CMD_INDEX_SYNONYMS_ADD0$raw$synonym);
        if (
$this->_bufSize 0) {
            
$this->appendBuffer(strval($cmd));
        } else {
            
$this->execCommand($cmdXS_CMD_OK_RQST_FINISHED);
        }
    }
    return 
$this;
}

添加同義詞

beginRebuild() 方法
public XSIndex beginRebuild()
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L391 (顯示)
public function beginRebuild()
{
    
$this->execCommand(array('cmd' => XS_CMD_INDEX_REBUILD'arg1' => 0), XS_CMD_OK_DB_REBUILD);
    
$this->_rebuild true;
    return 
$this;
}

開始重建索引 此后所有的索引更新指令將寫到臨時庫, 而不是當前搜索庫, 重建完成后調用 endRebuild 實現平滑重建索引, 重建過程仍可搜索舊的索引庫, 如直接用 clean 清空數據, 則會導致重建過程搜索到不全的數據

參見

clean() 方法
public XSIndex clean()
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L59 (顯示)
public function clean()
{
    
$this->execCommand(XS_CMD_INDEX_CLEAN_DBXS_CMD_OK_DB_CLEAN);
    return 
$this;
}

完全清空索引數據 如果當前數據庫處于重建過程中將禁止清空

參見

close() 方法
public void close($ioerr=false)
$ioerr
源碼: sdk/php/lib/XSIndex.class.php#L504 (顯示)
public function close($ioerr false)
{
    
$this->closeBuffer();
    
parent::close($ioerr);
}

關閉索引服務端連接

closeBuffer() 方法
public XSIndex closeBuffer()
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L378 (顯示)
public function closeBuffer()
{
    return 
$this->openBuffer(0);
}

提交所有指令并關閉緩沖區 若未曾打開緩沖區, 調用本方法是無意義的

參見

del() 方法
public XSIndex del(mixed $term, string $field=NULL)
$term mixed 單個主鍵或指定字段的索引詞, 或多個組成的數組, 編碼與 xs 默認字符集一致
$field string 索引詞所屬的字段名稱, 默認不指定則為主鍵字段 (類型為ID)
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L220 (顯示)
public function del($term$field null)
{
    
// get field
    
$field $field === null $this->xs->getFieldId() : $this->xs->getField($field);

    
// get commands
    
$cmds = array();
    
$terms is_array($term) ? array_unique($term) : array($term);
    
$terms XS::convert($terms'UTF-8'$this->xs->getDefaultCharset());
    foreach (
$terms as $term) {
        
$cmds[] = new XSCommand(XS_CMD_INDEX_REMOVE0$field->vnostrtolower($term));
    }

    
// combine multi commands into exdata
    
if ($this->_bufSize 0) {
        
$this->appendBuffer(implode(''$cmds));
    } elseif (
count($cmds) == 1) {
        
$this->execCommand($cmds[0], XS_CMD_OK_RQST_FINISHED);
    } else {
        
$cmd = array('cmd' => XS_CMD_INDEX_EXDATA'buf' => implode(''$cmds));
        
$this->execCommand($cmdXS_CMD_OK_RQST_FINISHED);
    }
    return 
$this;
}

刪除索引中的數據

$index->del('123');	// 刪除主鍵為 123 的記錄
$index->del(array('123', '789', '456')); // 刪除主鍵為 123, 789, 456 的記錄
$index->del('abc', 'field'); // 刪除字段 field 上帶有索引詞 abc 的所有記錄
$index->del(array('abc', 'def'), 'field'); // 刪除字段 field 上帶有索引詞 abc 或 def 的所有記錄

delSynonym() 方法 (自版本 v1.3.0 起可用)
public XSIndex delSynonym(string $raw, string $synonym=NULL)
$raw string 需要同義的原詞, 英文詞匯支持用空格分開多個單詞并強制被轉換為小寫
$synonym string 要刪除的同義詞條, 默認 null 表示刪除原詞下的所有同義詞
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L306 (顯示)
public function delSynonym($raw$synonym null)
{
    
$raw strval($raw);
    
$synonym $synonym === null '' strval($synonym);
    if (
$raw !== '') {
        
$cmd = new XSCommand(XS_CMD_INDEX_SYNONYMSXS_CMD_INDEX_SYNONYMS_DEL0$raw$synonym);
        if (
$this->_bufSize 0) {
            
$this->appendBuffer(strval($cmd));
        } else {
            
$this->execCommand($cmdXS_CMD_OK_RQST_FINISHED);
        }
    }
    return 
$this;
}

刪除某個同義詞

endRebuild() 方法
public XSIndex endRebuild()
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L404 (顯示)
public function endRebuild()
{
    if (
$this->_rebuild === true) {
        
$this->_rebuild false;
        
$this->execCommand(array('cmd' => XS_CMD_INDEX_REBUILD'arg1' => 1), XS_CMD_OK_DB_REBUILD);
    }
    return 
$this;
}

完成并關閉重建索引 重建完成后調用, 用重建好的索引數據代替舊的索引數據

參見

execCommand() 方法
public void execCommand($cmd, $res_arg=0, $res_cmd=128)
$cmd
$res_arg
$res_cmd
源碼: sdk/php/lib/XSIndex.class.php#L44 (顯示)
public function execCommand($cmd$res_arg XS_CMD_NONE$res_cmd XS_CMD_OK)
{
    
$res parent::execCommand($cmd$res_arg$res_cmd);
    foreach (
self::$_adds as $srv) {
        
$srv->execCommand($cmd$res_arg$res_cmd);
    }
    return 
$res;
}

執行服務端指令并獲取返回值 重寫此方法是為了同步到額外增加的多個索引服務端

flushIndex() 方法
public bool flushIndex()
{return} bool 刷新成功返回 true, 失敗則返回 false
源碼: sdk/php/lib/XSIndex.class.php#L466 (顯示)
public function flushIndex()
{
    try {
        
$this->execCommand(XS_CMD_INDEX_COMMITXS_CMD_OK_DB_COMMITED);
    } catch (
XSException $e) {
        if (
$e->getCode() === XS_CMD_ERR_BUSY || $e->getCode() === XS_CMD_ERR_RUNNING) {
            return 
false;
        }
        throw 
$e;
    }
    return 
true;
}

強制刷新服務端的當前庫的索引緩存

flushLogging() 方法
public bool flushLogging()
{return} bool 刷新成功返回 true, 失敗則返回 false
源碼: sdk/php/lib/XSIndex.class.php#L449 (顯示)
public function flushLogging()
{
    try {
        
$this->execCommand(XS_CMD_FLUSH_LOGGINGXS_CMD_OK_LOG_FLUSHED);
    } catch (
XSException $e) {
        if (
$e->getCode() === XS_CMD_ERR_BUSY) {
            return 
false;
        }
        throw 
$e;
    }
    return 
true;
}

強制刷新服務端當前項目的搜索日志

getCustomDict() 方法
public string getCustomDict()
{return} string 自定義詞庫內容
源碼: sdk/php/lib/XSIndex.class.php#L484 (顯示)
public function getCustomDict()
{
    
$res $this->execCommand(XS_CMD_INDEX_USER_DICTXS_CMD_OK_INFO);
    return 
$res->buf;
}

獲取自定義詞典內容

getScwsMulti() 方法 (自版本 v1.4.7 起可用)
public int getScwsMulti()
{return} int 返回當前庫的分詞復合等級
源碼: sdk/php/lib/XSIndex.class.php#L347 (顯示)
public function getScwsMulti()
{
    
$cmd = array('cmd' => XS_CMD_SEARCH_SCWS_GET'arg1' => XS_CMD_SCWS_GET_MULTI);
    
$res $this->execCommand($cmdXS_CMD_OK_INFO);
    return 
intval($res->buf);
}

獲取當前索引庫的分詞復合等級

參見

openBuffer() 方法
public XSIndex openBuffer(int $size=4)
$size int 緩沖區大小, 單位: MB 默認為 4MB
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L362 (顯示)
public function openBuffer($size 4)
{
    if (
$this->_buf !== '') {
        
$this->addExdata($this->_buffalse);
    }
    
$this->_bufSize intval($size) << 20;
    
$this->_buf '';
    return 
$this;
}

開啟索引命令提交緩沖區 為優化網絡性能, 有必要先將本地提交的 add/update/del 等索引變動指令緩存下來, 當總大小達到參數指定的 size 時或調用 closeBuffer 時再真正提交到服務器 注意: 此舉常用于需要大批量更新索引時, 此外重復調用本函數是無必要的

setCustomDict() 方法
public void setCustomDict(string $content)
$content string 新的詞典內容
源碼: sdk/php/lib/XSIndex.class.php#L495 (顯示)
public function setCustomDict($content)
{
    
$cmd = array('cmd' => XS_CMD_INDEX_USER_DICT'arg1' => 1'buf' => $content);
    
$this->execCommand($cmdXS_CMD_OK_DICT_SAVED);
}

設置自定義詞典內容

setDb() 方法
public XSIndex setDb(string $name)
$name string 數據庫名稱
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L439 (顯示)
public function setDb($name)
{
    
$this->execCommand(array('cmd' => XS_CMD_INDEX_SET_DB'buf' => $name), XS_CMD_OK_DB_CHANGED);
    return 
$this;
}

更改存放索引數據的目錄 默認索引數據保存到服務器上的 db 目錄, 通過此方法修改數據目錄名

setScwsMulti() 方法 (自版本 v1.4.7 起可用)
public XSIndex setScwsMulti(int $level)
$level int 要設置的分詞復合等級
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L331 (顯示)
public function setScwsMulti($level)
{
    
$level intval($level);
    if (
$level >= && $level 16) {
        
$cmd = array('cmd' => XS_CMD_SEARCH_SCWS_SET'arg1' => XS_CMD_SCWS_SET_MULTI'arg2' => $level);
        
$this->execCommand($cmd);
    }
    return 
$this;
}

設置當前索引庫的分詞復合等級 復合等級是 scws 分詞粒度控制的一個重要參數, 是長詞細分處理依據, 默認為 3, 值范圍 0~15 注意: 這個設置僅直對當前索引庫有效, 多次調用設置值被覆蓋僅最后那次設置有效, 而且僅對設置之后提交的索引數據起作用, 如需對以前的索引數據生效請重建索引.

stopRebuild() 方法 (自版本 v1.3.4 起可用)
public XSIndex stopRebuild()
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L420 (顯示)
public function stopRebuild()
{
    try {
        
$this->execCommand(array('cmd' => XS_CMD_INDEX_REBUILD'arg1' => 2), XS_CMD_OK_DB_REBUILD);
        
$this->_rebuild false;
    } catch (
XSException $e) {
        if (
$e->getCode() !== XS_CMD_ERR_WRONGPLACE) {
            throw 
$e;
        }
    }
    return 
$this;
}

中止索引重建 丟棄重建臨時庫的所有數據, 恢復成當前搜索庫, 主要用于偶爾重建意外中止的情況

參見

update() 方法
public XSIndex update(XSDocument $doc, bool $add=false)
$doc XSDocument
$add bool 是否為新增文檔, 已有數據中不存在同一主鍵的其它數據
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L85 (顯示)
public function update(XSDocument $doc$add false)
{
    
// before submit
    
if ($doc->beforeSubmit($this) === false) {
        return 
$this;
    }

    
// check primary key of document
    
$fid $this->xs->getFieldId();
    
$key $doc->f($fid);
    if (
$key === null || $key === '') {
        throw new 
XSException('Missing value of primary key (FIELD:' $fid ')');
    }

    
// request cmd
    
$cmd = new XSCommand(XS_CMD_INDEX_REQUESTXS_CMD_INDEX_REQUEST_ADD);
    if (
$add !== true) {
        
$cmd->arg1 XS_CMD_INDEX_REQUEST_UPDATE;
        
$cmd->arg2 $fid->vno;
        
$cmd->buf $key;
    }
    
$cmds = array($cmd);

    
// document cmds
    
foreach ($this->xs->getAllFields() as $field/* @var $field XSFieldMeta */ {
        
// value
        
if (($value $doc->f($field)) !== null) {
            
$varg $field->isNumeric() ? XS_CMD_VALUE_FLAG_NUMERIC 0;
            
$value $field->val($value);
            if (!
$field->hasCustomTokenizer()) {
                
// internal tokenizer
                
$wdf $field->weight | ($field->withPos() ? XS_CMD_INDEX_FLAG_WITHPOS 0);
                if (
$field->hasIndexMixed()) {
                    
$cmds[] = new XSCommand(XS_CMD_DOC_INDEX$wdfXSFieldScheme::MIXED_VNO$value);
                }
                if (
$field->hasIndexSelf()) {
                    
$wdf |= $field->isNumeric() ? XS_CMD_INDEX_FLAG_SAVEVALUE;
                    
$cmds[] = new XSCommand(XS_CMD_DOC_INDEX$wdf$field->vno$value);
                }
                
// add value
                
if (!$field->hasIndexSelf() || $field->isNumeric()) {
                    
$cmds[] = new XSCommand(XS_CMD_DOC_VALUE$varg$field->vno$value);
                }
            } else {
                
// add index
                
if ($field->hasIndex()) {
                    
$terms $field->getCustomTokenizer()->getTokens($value$doc);
                    
// self: [bool term, NOT weight, NOT stem, NOT pos]
                    
if ($field->hasIndexSelf()) {
                        
$wdf $field->isBoolIndex() ? : ($field->weight XS_CMD_INDEX_FLAG_CHECKSTEM);
                        foreach (
$terms as $term) {
                            if (
strlen($term) > 200) {
                                continue;
                            }
                            
$term strtolower($term);
                            
$cmds[] = new XSCommand(XS_CMD_DOC_TERM$wdf$field->vno$term);
                        }
                    }
                    
// mixed: [use default tokenizer]
                    
if ($field->hasIndexMixed()) {
                        
$mtext implode(' '$terms);
                        
$cmds[] = new XSCommand(XS_CMD_DOC_INDEX$field->weightXSFieldScheme::MIXED_VNO$mtext);
                    }
                }
                
// add value
                
$cmds[] = new XSCommand(XS_CMD_DOC_VALUE$varg$field->vno$value);
            }
        }
        
// process add terms
        
if (($terms $doc->getAddTerms($field)) !== null) {
            
// ignore weight for bool index
            
$wdf1 $field->isBoolIndex() ? XS_CMD_INDEX_FLAG_CHECKSTEM;
            foreach (
$terms as $term => $wdf) {
                
$term strtolower($term);
                if (
strlen($term) > 200) {
                    continue;
                }
                
$wdf2 $field->isBoolIndex() ? $wdf $field->weight;
                while (
$wdf2 XSFieldMeta::MAX_WDF) {
                    
$cmds[] = new XSCommand(XS_CMD_DOC_TERM$wdf1 XSFieldMeta::MAX_WDF$field->vno$term);
                    
$wdf2 -= XSFieldMeta::MAX_WDF;
                }
                
$cmds[] = new XSCommand(XS_CMD_DOC_TERM$wdf1 $wdf2$field->vno$term);
            }
        }
        
// process add text
        
if (($text $doc->getAddIndex($field)) !== null) {
            if (!
$field->hasCustomTokenizer()) {
                
$wdf $field->weight | ($field->withPos() ? XS_CMD_INDEX_FLAG_WITHPOS 0);
                
$cmds[] = new XSCommand(XS_CMD_DOC_INDEX$wdf$field->vno$text);
            } else {
                
// NOT pos
                
$wdf $field->isBoolIndex() ? : ($field->weight XS_CMD_INDEX_FLAG_CHECKSTEM);
                
$terms $field->getCustomTokenizer()->getTokens($text$doc);
                foreach (
$terms as $term) {
                    if (
strlen($term) > 200) {
                        continue;
                    }
                    
$term strtolower($term);
                    
$cmds[] = new XSCommand(XS_CMD_DOC_TERM$wdf$field->vno$term);
                }
            }
        }
    }

    
// submit cmd
    
$cmds[] = new XSCommand(XS_CMD_INDEX_SUBMIT);

    
// execute cmd
    
if ($this->_bufSize 0) {
        
$this->appendBuffer(implode(''$cmds));
    } else {
        for (
$i 0$i count($cmds) - 1$i++) {
            
$this->execCommand($cmds[$i]);
        }
        
$this->execCommand($cmds[$i], XS_CMD_OK_RQST_FINISHED);
    }

    
// after submit
    
$doc->afterSubmit($this);
    return 
$this;
}

更新索引文檔 該方法相當于先根據主鍵刪除已存在的舊文檔, 然后添加該文檔 如果你能明確認定是新文檔, 則建議使用 add

XSIndex - 類參考 - 迅搜(xunsearch) - 開源免費中文全文搜索引擎

文檔說明

XSIndex

XS
繼承關系 class XSIndex » XSServer » XSComponent
版本 1.0.0
源代碼 sdk/php/lib/XSIndex.class.php
XS 索引管理 添加/刪除/修改索引數據

Public 屬性

隱去繼承來的屬性

名稱類型描述定義于
connString string 連接字符串 XSServer
customDict string 獲取自定義詞典內容 XSIndex
project string 獲取當前項目名稱 XSServer
respond XSCommand 從服務器讀取響應指令 XSServer
scwsMulti int 獲取當前索引庫的分詞復合等級 XSIndex
socket mixed 獲取連接資源描述符 XSServer
xs XS 服務端關聯的 XS 對象 XSServer

Public 方法

隱去繼承來的方法

名稱描述定義于
__construct() 構造函數, 打開連接 XSServer
__destruct() 析構函數 XSIndex
__get() 魔術方法 __get XSComponent
__isset() 魔術方法 __isset XSComponent
__set() 魔術方法 __set XSComponent
__unset() 魔術方法 __unset XSComponent
add() 添加文檔到索引中 XSIndex
addExdata() 批量提交索引命令封包數據 XSIndex
addServer() 增加一個同步索引服務器 XSIndex
addSynonym() 添加同義詞 XSIndex
beginRebuild() 開始重建索引 XSIndex
clean() 完全清空索引數據 XSIndex
close() 關閉索引服務端連接 XSIndex
closeBuffer() 提交所有指令并關閉緩沖區 XSIndex
del() 刪除索引中的數據 XSIndex
delSynonym() 刪除某個同義詞 XSIndex
endRebuild() 完成并關閉重建索引 XSIndex
execCommand() 執行服務端指令并獲取返回值 XSIndex
flushIndex() 強制刷新服務端的當前庫的索引緩存 XSIndex
flushLogging() 強制刷新服務端當前項目的搜索日志 XSIndex
getConnString() Returns 連接字符串 XSServer
getCustomDict() 獲取自定義詞典內容 XSIndex
getProject() 獲取當前項目名稱 XSServer
getRespond() 從服務器讀取響應指令 XSServer
getScwsMulti() 獲取當前索引庫的分詞復合等級 XSIndex
getSocket() 獲取連接資源描述符 XSServer
hasRespond() 判斷服務端是否有可讀數據 XSServer
open() 打開服務端連接 XSServer
openBuffer() 開啟索引命令提交緩沖區 XSIndex
reopen() 重新打開連接 XSServer
sendCommand() 往服務器直接發送指令 (無緩存) XSServer
setCustomDict() 設置自定義詞典內容 XSIndex
setDb() 更改存放索引數據的目錄 XSIndex
setProject() 設置當前項目 XSServer
setScwsMulti() 設置當前索引庫的分詞復合等級 XSIndex
setTimeout() 設置服務端超時秒數 XSServer
stopRebuild() 中止索引重建 XSIndex
update() 更新索引文檔 XSIndex

Protected 方法

隱去繼承來的方法

名稱描述定義于
check() 檢測服務端的連接情況 XSServer
connect() 連接服務端 XSServer
read() 讀取數據 XSServer
write() 寫入數據 XSServer

屬性明細

customDict 屬性
public string getCustomDict()
public void setCustomDict(string $content)

獲取自定義詞典內容

scwsMulti 屬性 (自版本 v1.4.7 起可用)
public int getScwsMulti()
public XSIndex setScwsMulti(int $level)

獲取當前索引庫的分詞復合等級

參見

方法明細

__destruct() 方法
public void __destruct()
源碼: sdk/php/lib/XSIndex.class.php#L528 (顯示)
public function __destruct()
{
    if (
$this->_rebuild === true) {
        try {
            
$this->endRebuild();
        } catch (
Exception $e) {
            
        }
    }
    foreach (
self::$_adds as $srv) {
        
$srv->close();
    }
    
self::$_adds = array();
    
parent::__destruct();
}

析構函數 在此自動關閉開啟的 rebuild

add() 方法
public XSIndex add(XSDocument $doc)
$doc XSDocument
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L72 (顯示)
public function add(XSDocument $doc)
{
    return 
$this->update($doctrue);
}

添加文檔到索引中 特別要注意的是: 系統不會自動檢測主鍵是否沖突, 即便已存在相同主鍵也會添加進去

參見

addExdata() 方法
public XSIndex addExdata(string $data, bool $check_file=true)
$data string 要提交的命令封包數據, 或存儲命令封包的文件路徑, 編碼必須已經是 UTF-8
$check_file bool 是否檢測參數為文件的情況
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L253 (顯示)
public function addExdata($data$check_file true)
{
    if (
strlen($data) < 255 && $check_file
            
&& file_exists($data) && ($data file_get_contents($data)) === false) {
        throw new 
XSException('Failed to read exdata from file');
    }

    
// try to check allowed (BUG: check the first cmd only):
    // XS_CMD_IMPORT_HEADER, XS_CMD_INDEX_REQUEST, XS_CMD_INDEX_REMOVE, XS_CMD_INDEX_EXDATA
    
$first ord(substr($data01));
    if (
$first != XS_CMD_IMPORT_HEADER
            
&& $first != XS_CMD_INDEX_REQUEST && $first != XS_CMD_INDEX_SYNONYMS
            
&& $first != XS_CMD_INDEX_REMOVE && $first != XS_CMD_INDEX_EXDATA) {
        throw new 
XSException('Invalid start command of exdata (CMD:' $first ')');
    }

    
// create cmd & execute it
    
$cmd = array('cmd' => XS_CMD_INDEX_EXDATA'buf' => $data);
    
$this->execCommand($cmdXS_CMD_OK_RQST_FINISHED);
    return 
$this;
}

批量提交索引命令封包數據 把多個命令封包內容連續保存為文件或變量, 然后一次性提交以減少網絡開銷提升性能

addServer() 方法
public XSServer addServer(string $conn)
$conn string 索引服務端連接參數
{return} XSServer
源碼: sdk/php/lib/XSIndex.class.php#L33 (顯示)
public function addServer($conn)
{
    
$srv = new XSServer($conn$this->xs);
    
self::$_adds[] = $srv;
    return 
$srv;
}

增加一個同步索引服務器

addSynonym() 方法 (自版本 v1.3.0 起可用)
public XSIndex addSynonym(string $raw, string $synonym)
$raw string 需要同義的原詞, 英文詞匯支持用空格分開多個單詞并強制被轉換為小寫
$synonym string 同義詞條, 最小語素, 勿帶空格等分隔符
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L283 (顯示)
public function addSynonym($raw$synonym)
{
    
$raw strval($raw);
    
$synonym strval($synonym);
    if (
$raw !== '' && $synonym !== '') {
        
$cmd = new XSCommand(XS_CMD_INDEX_SYNONYMSXS_CMD_INDEX_SYNONYMS_ADD0$raw$synonym);
        if (
$this->_bufSize 0) {
            
$this->appendBuffer(strval($cmd));
        } else {
            
$this->execCommand($cmdXS_CMD_OK_RQST_FINISHED);
        }
    }
    return 
$this;
}

添加同義詞

beginRebuild() 方法
public XSIndex beginRebuild()
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L391 (顯示)
public function beginRebuild()
{
    
$this->execCommand(array('cmd' => XS_CMD_INDEX_REBUILD'arg1' => 0), XS_CMD_OK_DB_REBUILD);
    
$this->_rebuild true;
    return 
$this;
}

開始重建索引 此后所有的索引更新指令將寫到臨時庫, 而不是當前搜索庫, 重建完成后調用 endRebuild 實現平滑重建索引, 重建過程仍可搜索舊的索引庫, 如直接用 clean 清空數據, 則會導致重建過程搜索到不全的數據

參見

clean() 方法
public XSIndex clean()
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L59 (顯示)
public function clean()
{
    
$this->execCommand(XS_CMD_INDEX_CLEAN_DBXS_CMD_OK_DB_CLEAN);
    return 
$this;
}

完全清空索引數據 如果當前數據庫處于重建過程中將禁止清空

參見

close() 方法
public void close($ioerr=false)
$ioerr
源碼: sdk/php/lib/XSIndex.class.php#L504 (顯示)
public function close($ioerr false)
{
    
$this->closeBuffer();
    
parent::close($ioerr);
}

關閉索引服務端連接

closeBuffer() 方法
public XSIndex closeBuffer()
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L378 (顯示)
public function closeBuffer()
{
    return 
$this->openBuffer(0);
}

提交所有指令并關閉緩沖區 若未曾打開緩沖區, 調用本方法是無意義的

參見

del() 方法
public XSIndex del(mixed $term, string $field=NULL)
$term mixed 單個主鍵或指定字段的索引詞, 或多個組成的數組, 編碼與 xs 默認字符集一致
$field string 索引詞所屬的字段名稱, 默認不指定則為主鍵字段 (類型為ID)
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L220 (顯示)
public function del($term$field null)
{
    
// get field
    
$field $field === null $this->xs->getFieldId() : $this->xs->getField($field);

    
// get commands
    
$cmds = array();
    
$terms is_array($term) ? array_unique($term) : array($term);
    
$terms XS::convert($terms'UTF-8'$this->xs->getDefaultCharset());
    foreach (
$terms as $term) {
        
$cmds[] = new XSCommand(XS_CMD_INDEX_REMOVE0$field->vnostrtolower($term));
    }

    
// combine multi commands into exdata
    
if ($this->_bufSize 0) {
        
$this->appendBuffer(implode(''$cmds));
    } elseif (
count($cmds) == 1) {
        
$this->execCommand($cmds[0], XS_CMD_OK_RQST_FINISHED);
    } else {
        
$cmd = array('cmd' => XS_CMD_INDEX_EXDATA'buf' => implode(''$cmds));
        
$this->execCommand($cmdXS_CMD_OK_RQST_FINISHED);
    }
    return 
$this;
}

刪除索引中的數據

$index->del('123');	// 刪除主鍵為 123 的記錄
$index->del(array('123', '789', '456')); // 刪除主鍵為 123, 789, 456 的記錄
$index->del('abc', 'field'); // 刪除字段 field 上帶有索引詞 abc 的所有記錄
$index->del(array('abc', 'def'), 'field'); // 刪除字段 field 上帶有索引詞 abc 或 def 的所有記錄

delSynonym() 方法 (自版本 v1.3.0 起可用)
public XSIndex delSynonym(string $raw, string $synonym=NULL)
$raw string 需要同義的原詞, 英文詞匯支持用空格分開多個單詞并強制被轉換為小寫
$synonym string 要刪除的同義詞條, 默認 null 表示刪除原詞下的所有同義詞
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L306 (顯示)
public function delSynonym($raw$synonym null)
{
    
$raw strval($raw);
    
$synonym $synonym === null '' strval($synonym);
    if (
$raw !== '') {
        
$cmd = new XSCommand(XS_CMD_INDEX_SYNONYMSXS_CMD_INDEX_SYNONYMS_DEL0$raw$synonym);
        if (
$this->_bufSize 0) {
            
$this->appendBuffer(strval($cmd));
        } else {
            
$this->execCommand($cmdXS_CMD_OK_RQST_FINISHED);
        }
    }
    return 
$this;
}

刪除某個同義詞

endRebuild() 方法
public XSIndex endRebuild()
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L404 (顯示)
public function endRebuild()
{
    if (
$this->_rebuild === true) {
        
$this->_rebuild false;
        
$this->execCommand(array('cmd' => XS_CMD_INDEX_REBUILD'arg1' => 1), XS_CMD_OK_DB_REBUILD);
    }
    return 
$this;
}

完成并關閉重建索引 重建完成后調用, 用重建好的索引數據代替舊的索引數據

參見

execCommand() 方法
public void execCommand($cmd, $res_arg=0, $res_cmd=128)
$cmd
$res_arg
$res_cmd
源碼: sdk/php/lib/XSIndex.class.php#L44 (顯示)
public function execCommand($cmd$res_arg XS_CMD_NONE$res_cmd XS_CMD_OK)
{
    
$res parent::execCommand($cmd$res_arg$res_cmd);
    foreach (
self::$_adds as $srv) {
        
$srv->execCommand($cmd$res_arg$res_cmd);
    }
    return 
$res;
}

執行服務端指令并獲取返回值 重寫此方法是為了同步到額外增加的多個索引服務端

flushIndex() 方法
public bool flushIndex()
{return} bool 刷新成功返回 true, 失敗則返回 false
源碼: sdk/php/lib/XSIndex.class.php#L466 (顯示)
public function flushIndex()
{
    try {
        
$this->execCommand(XS_CMD_INDEX_COMMITXS_CMD_OK_DB_COMMITED);
    } catch (
XSException $e) {
        if (
$e->getCode() === XS_CMD_ERR_BUSY || $e->getCode() === XS_CMD_ERR_RUNNING) {
            return 
false;
        }
        throw 
$e;
    }
    return 
true;
}

強制刷新服務端的當前庫的索引緩存

flushLogging() 方法
public bool flushLogging()
{return} bool 刷新成功返回 true, 失敗則返回 false
源碼: sdk/php/lib/XSIndex.class.php#L449 (顯示)
public function flushLogging()
{
    try {
        
$this->execCommand(XS_CMD_FLUSH_LOGGINGXS_CMD_OK_LOG_FLUSHED);
    } catch (
XSException $e) {
        if (
$e->getCode() === XS_CMD_ERR_BUSY) {
            return 
false;
        }
        throw 
$e;
    }
    return 
true;
}

強制刷新服務端當前項目的搜索日志

getCustomDict() 方法
public string getCustomDict()
{return} string 自定義詞庫內容
源碼: sdk/php/lib/XSIndex.class.php#L484 (顯示)
public function getCustomDict()
{
    
$res $this->execCommand(XS_CMD_INDEX_USER_DICTXS_CMD_OK_INFO);
    return 
$res->buf;
}

獲取自定義詞典內容

getScwsMulti() 方法 (自版本 v1.4.7 起可用)
public int getScwsMulti()
{return} int 返回當前庫的分詞復合等級
源碼: sdk/php/lib/XSIndex.class.php#L347 (顯示)
public function getScwsMulti()
{
    
$cmd = array('cmd' => XS_CMD_SEARCH_SCWS_GET'arg1' => XS_CMD_SCWS_GET_MULTI);
    
$res $this->execCommand($cmdXS_CMD_OK_INFO);
    return 
intval($res->buf);
}

獲取當前索引庫的分詞復合等級

參見

openBuffer() 方法
public XSIndex openBuffer(int $size=4)
$size int 緩沖區大小, 單位: MB 默認為 4MB
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L362 (顯示)
public function openBuffer($size 4)
{
    if (
$this->_buf !== '') {
        
$this->addExdata($this->_buffalse);
    }
    
$this->_bufSize intval($size) << 20;
    
$this->_buf '';
    return 
$this;
}

開啟索引命令提交緩沖區 為優化網絡性能, 有必要先將本地提交的 add/update/del 等索引變動指令緩存下來, 當總大小達到參數指定的 size 時或調用 closeBuffer 時再真正提交到服務器 注意: 此舉常用于需要大批量更新索引時, 此外重復調用本函數是無必要的

setCustomDict() 方法
public void setCustomDict(string $content)
$content string 新的詞典內容
源碼: sdk/php/lib/XSIndex.class.php#L495 (顯示)
public function setCustomDict($content)
{
    
$cmd = array('cmd' => XS_CMD_INDEX_USER_DICT'arg1' => 1'buf' => $content);
    
$this->execCommand($cmdXS_CMD_OK_DICT_SAVED);
}

設置自定義詞典內容

setDb() 方法
public XSIndex setDb(string $name)
$name string 數據庫名稱
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L439 (顯示)
public function setDb($name)
{
    
$this->execCommand(array('cmd' => XS_CMD_INDEX_SET_DB'buf' => $name), XS_CMD_OK_DB_CHANGED);
    return 
$this;
}

更改存放索引數據的目錄 默認索引數據保存到服務器上的 db 目錄, 通過此方法修改數據目錄名

setScwsMulti() 方法 (自版本 v1.4.7 起可用)
public XSIndex setScwsMulti(int $level)
$level int 要設置的分詞復合等級
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L331 (顯示)
public function setScwsMulti($level)
{
    
$level intval($level);
    if (
$level >= && $level 16) {
        
$cmd = array('cmd' => XS_CMD_SEARCH_SCWS_SET'arg1' => XS_CMD_SCWS_SET_MULTI'arg2' => $level);
        
$this->execCommand($cmd);
    }
    return 
$this;
}

設置當前索引庫的分詞復合等級 復合等級是 scws 分詞粒度控制的一個重要參數, 是長詞細分處理依據, 默認為 3, 值范圍 0~15 注意: 這個設置僅直對當前索引庫有效, 多次調用設置值被覆蓋僅最后那次設置有效, 而且僅對設置之后提交的索引數據起作用, 如需對以前的索引數據生效請重建索引.

stopRebuild() 方法 (自版本 v1.3.4 起可用)
public XSIndex stopRebuild()
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L420 (顯示)
public function stopRebuild()
{
    try {
        
$this->execCommand(array('cmd' => XS_CMD_INDEX_REBUILD'arg1' => 2), XS_CMD_OK_DB_REBUILD);
        
$this->_rebuild false;
    } catch (
XSException $e) {
        if (
$e->getCode() !== XS_CMD_ERR_WRONGPLACE) {
            throw 
$e;
        }
    }
    return 
$this;
}

中止索引重建 丟棄重建臨時庫的所有數據, 恢復成當前搜索庫, 主要用于偶爾重建意外中止的情況

參見

update() 方法
public XSIndex update(XSDocument $doc, bool $add=false)
$doc XSDocument
$add bool 是否為新增文檔, 已有數據中不存在同一主鍵的其它數據
{return} XSIndex 返回自身對象以支持串接操作
源碼: sdk/php/lib/XSIndex.class.php#L85 (顯示)
public function update(XSDocument $doc$add false)
{
    
// before submit
    
if ($doc->beforeSubmit($this) === false) {
        return 
$this;
    }

    
// check primary key of document
    
$fid $this->xs->getFieldId();
    
$key $doc->f($fid);
    if (
$key === null || $key === '') {
        throw new 
XSException('Missing value of primary key (FIELD:' $fid ')');
    }

    
// request cmd
    
$cmd = new XSCommand(XS_CMD_INDEX_REQUESTXS_CMD_INDEX_REQUEST_ADD);
    if (
$add !== true) {
        
$cmd->arg1 XS_CMD_INDEX_REQUEST_UPDATE;
        
$cmd->arg2 $fid->vno;
        
$cmd->buf $key;
    }
    
$cmds = array($cmd);

    
// document cmds
    
foreach ($this->xs->getAllFields() as $field/* @var $field XSFieldMeta */ {
        
// value
        
if (($value $doc->f($field)) !== null) {
            
$varg $field->isNumeric() ? XS_CMD_VALUE_FLAG_NUMERIC 0;
            
$value $field->val($value);
            if (!
$field->hasCustomTokenizer()) {
                
// internal tokenizer
                
$wdf $field->weight | ($field->withPos() ? XS_CMD_INDEX_FLAG_WITHPOS 0);
                if (
$field->hasIndexMixed()) {
                    
$cmds[] = new XSCommand(XS_CMD_DOC_INDEX$wdfXSFieldScheme::MIXED_VNO$value);
                }
                if (
$field->hasIndexSelf()) {
                    
$wdf |= $field->isNumeric() ? XS_CMD_INDEX_FLAG_SAVEVALUE;
                    
$cmds[] = new XSCommand(XS_CMD_DOC_INDEX$wdf$field->vno$value);
                }
                
// add value
                
if (!$field->hasIndexSelf() || $field->isNumeric()) {
                    
$cmds[] = new XSCommand(XS_CMD_DOC_VALUE$varg$field->vno$value);
                }
            } else {
                
// add index
                
if ($field->hasIndex()) {
                    
$terms $field->getCustomTokenizer()->getTokens($value$doc);
                    
// self: [bool term, NOT weight, NOT stem, NOT pos]
                    
if ($field->hasIndexSelf()) {
                        
$wdf $field->isBoolIndex() ? : ($field->weight XS_CMD_INDEX_FLAG_CHECKSTEM);
                        foreach (
$terms as $term) {
                            if (
strlen($term) > 200) {
                                continue;
                            }
                            
$term strtolower($term);
                            
$cmds[] = new XSCommand(XS_CMD_DOC_TERM$wdf$field->vno$term);
                        }
                    }
                    
// mixed: [use default tokenizer]
                    
if ($field->hasIndexMixed()) {
                        
$mtext implode(' '$terms);
                        
$cmds[] = new XSCommand(XS_CMD_DOC_INDEX$field->weightXSFieldScheme::MIXED_VNO$mtext);
                    }
                }
                
// add value
                
$cmds[] = new XSCommand(XS_CMD_DOC_VALUE$varg$field->vno$value);
            }
        }
        
// process add terms
        
if (($terms $doc->getAddTerms($field)) !== null) {
            
// ignore weight for bool index
            
$wdf1 $field->isBoolIndex() ? XS_CMD_INDEX_FLAG_CHECKSTEM;
            foreach (
$terms as $term => $wdf) {
                
$term strtolower($term);
                if (
strlen($term) > 200) {
                    continue;
                }
                
$wdf2 $field->isBoolIndex() ? $wdf $field->weight;
                while (
$wdf2 XSFieldMeta::MAX_WDF) {
                    
$cmds[] = new XSCommand(XS_CMD_DOC_TERM$wdf1 XSFieldMeta::MAX_WDF$field->vno$term);
                    
$wdf2 -= XSFieldMeta::MAX_WDF;
                }
                
$cmds[] = new XSCommand(XS_CMD_DOC_TERM$wdf1 $wdf2$field->vno$term);
            }
        }
        
// process add text
        
if (($text $doc->getAddIndex($field)) !== null) {
            if (!
$field->hasCustomTokenizer()) {
                
$wdf $field->weight | ($field->withPos() ? XS_CMD_INDEX_FLAG_WITHPOS 0);
                
$cmds[] = new XSCommand(XS_CMD_DOC_INDEX$wdf$field->vno$text);
            } else {
                
// NOT pos
                
$wdf $field->isBoolIndex() ? : ($field->weight XS_CMD_INDEX_FLAG_CHECKSTEM);
                
$terms $field->getCustomTokenizer()->getTokens($text$doc);
                foreach (
$terms as $term) {
                    if (
strlen($term) > 200) {
                        continue;
                    }
                    
$term strtolower($term);
                    
$cmds[] = new XSCommand(XS_CMD_DOC_TERM$wdf$field->vno$term);
                }
            }
        }
    }

    
// submit cmd
    
$cmds[] = new XSCommand(XS_CMD_INDEX_SUBMIT);

    
// execute cmd
    
if ($this->_bufSize 0) {
        
$this->appendBuffer(implode(''$cmds));
    } else {
        for (
$i 0$i count($cmds) - 1$i++) {
            
$this->execCommand($cmds[$i]);
        }
        
$this->execCommand($cmds[$i], XS_CMD_OK_RQST_FINISHED);
    }

    
// after submit
    
$doc->afterSubmit($this);
    return 
$this;
}

更新索引文檔 該方法相當于先根據主鍵刪除已存在的舊文檔, 然后添加該文檔 如果你能明確認定是新文檔, 則建議使用 add

一條評論!

#56 報告
xiaolingzi at 2015-06-29 17:12:23
flushIndex導致數據重復的問題

在調用了add方法后立馬調用flushIndex()會出現該document被建立了兩條索引了

請到論壇 登錄 后刷新本頁面!

青海快三开奖走势图_ 英超赛程分析中国网 黑桃棋牌手游官方网 美人捕鱼游戏机价格 赚q币 pc蛋蛋除外 正规分分彩计划app 讧苏11选5基本走势图 北京pk10牛牛技巧 腾讯分分彩是什么 网赚平台 免费麻将游戏大全