📄 sphinxapi.php
字号:
continue;
}
}
// read schema
$fields = array ();
$attrs = array ();
list(,$nfields) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
while ( $nfields-->0 && $p<$max )
{
list(,$len) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
$fields[] = substr ( $response, $p, $len ); $p += $len;
}
$result["fields"] = $fields;
list(,$nattrs) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
while ( $nattrs-->0 && $p<$max )
{
list(,$len) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
$attr = substr ( $response, $p, $len ); $p += $len;
list(,$type) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
$attrs[$attr] = $type;
}
$result["attrs"] = $attrs;
// read match count
list(,$count) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
list(,$id64) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
// read matches
$idx = -1;
while ( $count-->0 && $p<$max )
{
// index into result array
$idx++;
// parse document id and weight
if ( $id64 )
{
$doc = sphUnpack64 ( substr ( $response, $p, 8 ) ); $p += 8;
list(,$weight) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
} else
{
list ( $doc, $weight ) = array_values ( unpack ( "N*N*",
substr ( $response, $p, 8 ) ) );
$p += 8;
if ( PHP_INT_SIZE>=8 )
{
// x64 route, workaround broken unpack() in 5.2.2+
if ( $doc<0 ) $doc += (1<<32);
} else
{
// x32 route, workaround php signed/unsigned braindamage
$doc = sprintf ( "%u", $doc );
}
}
$weight = sprintf ( "%u", $weight );
// create match entry
if ( $this->_arrayresult )
$result["matches"][$idx] = array ( "id"=>$doc, "weight"=>$weight );
else
$result["matches"][$doc]["weight"] = $weight;
// parse and create attributes
$attrvals = array ();
foreach ( $attrs as $attr=>$type )
{
// handle floats
if ( $type==SPH_ATTR_FLOAT )
{
list(,$uval) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
list(,$fval) = unpack ( "f*", pack ( "L", $uval ) );
$attrvals[$attr] = $fval;
continue;
}
// handle everything else as unsigned ints
list(,$val) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
if ( $type & SPH_ATTR_MULTI )
{
$attrvals[$attr] = array ();
$nvalues = $val;
while ( $nvalues-->0 && $p<$max )
{
list(,$val) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
$attrvals[$attr][] = sprintf ( "%u", $val );
}
} else
{
$attrvals[$attr] = sprintf ( "%u", $val );
}
}
if ( $this->_arrayresult )
$result["matches"][$idx]["attrs"] = $attrvals;
else
$result["matches"][$doc]["attrs"] = $attrvals;
}
list ( $total, $total_found, $msecs, $words ) =
array_values ( unpack ( "N*N*N*N*", substr ( $response, $p, 16 ) ) );
$result["total"] = sprintf ( "%u", $total );
$result["total_found"] = sprintf ( "%u", $total_found );
$result["time"] = sprintf ( "%.3f", $msecs/1000 );
$p += 16;
while ( $words-->0 && $p<$max )
{
list(,$len) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
$word = substr ( $response, $p, $len ); $p += $len;
list ( $docs, $hits ) = array_values ( unpack ( "N*N*", substr ( $response, $p, 8 ) ) ); $p += 8;
$result["words"][$word] = array (
"docs"=>sprintf ( "%u", $docs ),
"hits"=>sprintf ( "%u", $hits ) );
}
}
$this->_MBPop ();
return $results;
}
/////////////////////////////////////////////////////////////////////////////
// excerpts generation
/////////////////////////////////////////////////////////////////////////////
/// connect to searchd server, and generate exceprts (snippets)
/// of given documents for given query. returns false on failure,
/// an array of snippets on success
function BuildExcerpts ( $docs, $index, $words, $opts=array() )
{
assert ( is_array($docs) );
assert ( is_string($index) );
assert ( is_string($words) );
assert ( is_array($opts) );
$this->_MBPush ();
if (!( $fp = $this->_Connect() ))
{
$this->_MBPop();
return false;
}
/////////////////
// fixup options
/////////////////
if ( !isset($opts["before_match"]) ) $opts["before_match"] = "<b>";
if ( !isset($opts["after_match"]) ) $opts["after_match"] = "</b>";
if ( !isset($opts["chunk_separator"]) ) $opts["chunk_separator"] = " ... ";
if ( !isset($opts["limit"]) ) $opts["limit"] = 256;
if ( !isset($opts["around"]) ) $opts["around"] = 5;
if ( !isset($opts["exact_phrase"]) ) $opts["exact_phrase"] = false;
if ( !isset($opts["single_passage"]) ) $opts["single_passage"] = false;
if ( !isset($opts["use_boundaries"]) ) $opts["use_boundaries"] = false;
if ( !isset($opts["weight_order"]) ) $opts["weight_order"] = false;
/////////////////
// build request
/////////////////
// v.1.0 req
$flags = 1; // remove spaces
if ( $opts["exact_phrase"] ) $flags |= 2;
if ( $opts["single_passage"] ) $flags |= 4;
if ( $opts["use_boundaries"] ) $flags |= 8;
if ( $opts["weight_order"] ) $flags |= 16;
$req = pack ( "NN", 0, $flags ); // mode=0, flags=$flags
$req .= pack ( "N", strlen($index) ) . $index; // req index
$req .= pack ( "N", strlen($words) ) . $words; // req words
// options
$req .= pack ( "N", strlen($opts["before_match"]) ) . $opts["before_match"];
$req .= pack ( "N", strlen($opts["after_match"]) ) . $opts["after_match"];
$req .= pack ( "N", strlen($opts["chunk_separator"]) ) . $opts["chunk_separator"];
$req .= pack ( "N", (int)$opts["limit"] );
$req .= pack ( "N", (int)$opts["around"] );
// documents
$req .= pack ( "N", count($docs) );
foreach ( $docs as $doc )
{
assert ( is_string($doc) );
$req .= pack ( "N", strlen($doc) ) . $doc;
}
////////////////////////////
// send query, get response
////////////////////////////
$len = strlen($req);
$req = pack ( "nnN", SEARCHD_COMMAND_EXCERPT, VER_COMMAND_EXCERPT, $len ) . $req; // add header
$wrote = fwrite ( $fp, $req, $len+8 );
if (!( $response = $this->_GetResponse ( $fp, VER_COMMAND_EXCERPT ) ))
{
$this->_MBPop ();
return false;
}
//////////////////
// parse response
//////////////////
$pos = 0;
$res = array ();
$rlen = strlen($response);
for ( $i=0; $i<count($docs); $i++ )
{
list(,$len) = unpack ( "N*", substr ( $response, $pos, 4 ) );
$pos += 4;
if ( $pos+$len > $rlen )
{
$this->_error = "incomplete reply";
$this->_MBPop ();
return false;
}
$res[] = $len ? substr ( $response, $pos, $len ) : "";
$pos += $len;
}
$this->_MBPop ();
return $res;
}
/////////////////////////////////////////////////////////////////////////////
// keyword generation
/////////////////////////////////////////////////////////////////////////////
/// connect to searchd server, and generate keyword list for a given query
/// returns false on failure,
/// an array of words on success
function BuildKeywords ( $query, $index, $hits )
{
assert ( is_string($query) );
assert ( is_string($index) );
assert ( is_bool($hits) );
$this->_MBPush ();
if (!( $fp = $this->_Connect() ))
{
$this->_MBPop();
return false;
}
/////////////////
// build request
/////////////////
// v.1.0 req
$req = pack ( "N", strlen($query) ) . $query; // req query
$req .= pack ( "N", strlen($index) ) . $index; // req index
$req .= pack ( "N", (int)$hits );
////////////////////////////
// send query, get response
////////////////////////////
$len = strlen($req);
$req = pack ( "nnN", SEARCHD_COMMAND_KEYWORDS, VER_COMMAND_KEYWORDS, $len ) . $req; // add header
$wrote = fwrite ( $fp, $req, $len+8 );
if (!( $response = $this->_GetResponse ( $fp, VER_COMMAND_KEYWORDS ) ))
{
$this->_MBPop ();
return false;
}
//////////////////
// parse response
//////////////////
$pos = 0;
$res = array ();
$rlen = strlen($response);
list(,$nwords) = unpack ( "N*", substr ( $response, $pos, 4 ) );
$pos += 4;
for ( $i=0; $i<$nwords; $i++ )
{
list(,$len) = unpack ( "N*", substr ( $response, $pos, 4 ) ); $pos += 4;
$tokenized = $len ? substr ( $response, $pos, $len ) : "";
$pos += $len;
list(,$len) = unpack ( "N*", substr ( $response, $pos, 4 ) ); $pos += 4;
$normalized = $len ? substr ( $response, $pos, $len ) : "";
$pos += $len;
$res[] = array ( "tokenized"=>$tokenized, "normalized"=>$normalized );
if ( $hits )
{
list($ndocs,$nhits) = array_values ( unpack ( "N*N*", substr ( $response, $pos, 8 ) ) );
$pos += 8;
$res [$i]["docs"] = $ndocs;
$res [$i]["hits"] = $nhits;
}
if ( $pos > $rlen )
{
$this->_error = "incomplete reply";
$this->_MBPop ();
return false;
}
}
$this->_MBPop ();
return $res;
}
function EscapeString ( $string )
{
$from = array ( '(',')','|','-','!','@','~','\"','&' );
$to = array ( '\\(','\\)','\\|','\\-','\\!','\\@','\\~','\\\"', '\\&' );
return str_replace ( $from, $to, $string );
}
/////////////////////////////////////////////////////////////////////////////
// attribute updates
/////////////////////////////////////////////////////////////////////////////
/// update given attribute values on given documents in given indexes
/// returns amount of updated documents (0 or more) on success, or -1 on failure
function UpdateAttributes ( $index, $attrs, $values )
{
// verify everything
assert ( is_string($index) );
assert ( is_array($attrs) );
foreach ( $attrs as $attr )
assert ( is_string($attr) );
assert ( is_array($values) );
foreach ( $values as $id=>$entry )
{
assert ( is_numeric($id) );
assert ( is_array($entry) );
assert ( count($entry)==count($attrs) );
foreach ( $entry as $v )
assert ( is_int($v) );
}
// build request
$req = pack ( "N", strlen($index) ) . $index;
$req .= pack ( "N", count($attrs) );
foreach ( $attrs as $attr )
$req .= pack ( "N", strlen($attr) ) . $attr;
$req .= pack ( "N", count($values) );
foreach ( $values as $id=>$entry )
{
$req .= sphPack64 ( $id );
foreach ( $entry as $v )
$req .= pack ( "N", $v );
}
// mbstring workaround
$this->_MBPush ();
// connect, send query, get response
if (!( $fp = $this->_Connect() ))
{
$this->_MBPop ();
return -1;
}
$len = strlen($req);
$req = pack ( "nnN", SEARCHD_COMMAND_UPDATE, VER_COMMAND_UPDATE, $len ) . $req; // add header
fwrite ( $fp, $req, $len+8 );
if (!( $response = $this->_GetResponse ( $fp, VER_COMMAND_UPDATE ) ))
{
$this->_MBPop ();
return -1;
}
// parse response
list(,$updated) = unpack ( "N*", substr ( $response, 0, 4 ) );
$this->_MBPop ();
return $updated;
}
}
//
// $Id$
//
?>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -