public function update(XSDocument $doc, $add = false) { if ($doc->beforeSubmit($this) === false) { return $this; } $fid = $this->xs->getFieldId(); $key = $doc->f($fid); if ($key === null || $key === '') { throw new XSException('Missing value of primary key (FIELD:' . $fid . ')'); } $cmd = new XSCommand(XS_CMD_INDEX_REQUEST, XS_CMD_INDEX_REQUEST_ADD); if ($add !== true) { $cmd->arg1 = XS_CMD_INDEX_REQUEST_UPDATE; $cmd->arg2 = $fid->vno; $cmd->buf = $key; } $cmds = array($cmd); foreach ($this->xs->getAllFields() as $field) { if (($value = $doc->f($field)) !== null) { $varg = $field->isNumeric() ? XS_CMD_VALUE_FLAG_NUMERIC : 0; $value = $field->val($value); if (!$field->hasCustomTokenizer()) { $wdf = $field->weight | ($field->withPos() ? XS_CMD_INDEX_FLAG_WITHPOS : 0); if ($field->hasIndexMixed()) { $cmds[] = new XSCommand(XS_CMD_DOC_INDEX, $wdf, XSFieldScheme::MIXED_VNO, $value); } if ($field->hasIndexSelf()) { $wdf |= $field->isNumeric() ? 0 : XS_CMD_INDEX_FLAG_SAVEVALUE; $cmds[] = new XSCommand(XS_CMD_DOC_INDEX, $wdf, $field->vno, $value); } if (!$field->hasIndexSelf() || $field->isNumeric()) { $cmds[] = new XSCommand(XS_CMD_DOC_VALUE, $varg, $field->vno, $value); } } else { if ($field->hasIndex()) { $terms = $field->getCustomTokenizer()->getTokens($value, $doc); if ($field->hasIndexSelf()) { $wdf = $field->isBoolIndex() ? 1 : $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); } } if ($field->hasIndexMixed()) { $mtext = implode(' ', $terms); $cmds[] = new XSCommand(XS_CMD_DOC_INDEX, $field->weight, XSFieldScheme::MIXED_VNO, $mtext); } } $cmds[] = new XSCommand(XS_CMD_DOC_VALUE, $varg, $field->vno, $value); } } if (($terms = $doc->getAddTerms($field)) !== null) { $wdf1 = $field->isBoolIndex() ? 0 : XS_CMD_INDEX_FLAG_CHECKSTEM; foreach ($terms as $term => $wdf) { $term = strtolower($term); if (strlen($term) > 200) { continue; } $wdf2 = $field->isBoolIndex() ? 1 : $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); } } 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 { $wdf = $field->isBoolIndex() ? 1 : $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); } } } } $cmds[] = new XSCommand(XS_CMD_INDEX_SUBMIT); 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); } $doc->afterSubmit($this); return $this; }
/** * 更新索引文档 * 该方法相当于先根据主键删除已存在的旧文档, 然后添加该文档 * 如果你能明确认定是新文档, 则建议使用 {@link add} * @param XSDocument $doc * @param bool $add 是否为新增文档, 已有数据中不存在同一主键的其它数据 * @return XSIndex 返回自身对象以支持串接操作 */ 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 primarky key (FIELD:' . $fid . ')'); } // request cmd $cmd = new XSCommand(CMD_INDEX_REQUEST, CMD_INDEX_REQUEST_ADD); if ($add !== true) { $cmd->arg1 = CMD_INDEX_REQUEST_UPDATE; $cmd->arg2 = $fid->vno; $cmd->buf = $key; } $cmds = array($cmd); // document cmds foreach ($this->xs->getAllFields() as $field) { // value if (($value = $doc->f($field)) !== null) { $varg = $field->isNumeric() ? CMD_VALUE_FLAG_NUMERIC : 0; $value = $field->val($value); if (!$field->hasCustomTokenizer()) { // internal tokenizer $wdf = $field->weight | ($field->withPos() ? CMD_INDEX_FLAG_WITHPOS : 0); if ($field->hasIndexMixed()) { $cmds[] = new XSCommand(CMD_DOC_INDEX, $wdf, XSFieldScheme::MIXED_VNO, $value); } if ($field->hasIndexSelf()) { $wdf |= $field->isNumeric() ? 0 : CMD_INDEX_FLAG_SAVEVALUE; $cmds[] = new XSCommand(CMD_DOC_INDEX, $wdf, $field->vno, $value); } // add value if (!$field->hasIndexSelf() || $field->isNumeric()) { $cmds[] = new XSCommand(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()) { foreach ($terms as $term) { $term = strtolower($term); $cmds[] = new XSCommand(CMD_DOC_TERM, 1, $field->vno, $term); } } // mixed: [use default tokenizer] if ($field->hasIndexMixed()) { $mtext = implode(' ', $terms); $cmds[] = new XSCommand(CMD_DOC_INDEX, $field->weight, XSFieldScheme::MIXED_VNO, $mtext); } } // add value $cmds[] = new XSCommand(CMD_DOC_VALUE, $varg, $field->vno, $value); } } // process add terms if (($terms = $doc->getAddTerms($field)) !== null) { // ignore weight for bool index $wdf1 = $field->isBoolIndex() ? 0 : CMD_INDEX_FLAG_CHECKSTEM; foreach ($terms as $term => $wdf) { $term = strtolower($term); $wdf2 = $field->isBoolIndex() ? 1 : $wdf * $field->weight; while ($wdf2 > XSFieldMeta::MAX_WDF) { $cmds[] = new XSCommand(CMD_DOC_TERM, $wdf1 | XSFieldMeta::MAX_WDF, $field->vno, $term); $wdf2 -= XSFieldMeta::MAX_WDF; } $cmds[] = new XSCommand(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() ? CMD_INDEX_FLAG_WITHPOS : 0); $cmds[] = new XSCommand(CMD_DOC_INDEX, $wdf, $field->vno, $text); } else { // NOT pos $wdf = $field->isBoolIndex() ? 1 : $field->weight | CMD_INDEX_FLAG_CHECKSTEM; $terms = $field->getCustomTokenizer()->getTokens($text, $doc); foreach ($terms as $term) { $term = strtolower($term); $cmds[] = new XSCommand(CMD_DOC_TERM, $wdf, $field->vno, $term); } } } } // submit cmd $cmds[] = new XSCommand(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], CMD_OK_RQST_FINISHED); } // after submit $doc->afterSubmit($this); return $this; }