您可以在各种操作系统上轻松安装并启动 Manticore,包括 Ubuntu、Centos、Debian、Windows 和 MacOS。此外,您还可以将 Manticore 作为 Docker 容器使用。
- Ubuntu
- Debian
- Centos
- Windows
- MacOS
- Docker
wget https://repo.manticoresearch.com/manticore-repo.noarch.deb
sudo dpkg -i manticore-repo.noarch.deb
sudo apt update
sudo apt install manticore manticore-columnar-lib
sudo systemctl start manticorewget https://repo.manticoresearch.com/manticore-repo.noarch.deb
sudo dpkg -i manticore-repo.noarch.deb
sudo apt update
sudo apt install manticore manticore-columnar-lib
sudo systemctl start manticoresudo yum install https://repo.manticoresearch.com/manticore-repo.noarch.rpm
sudo yum install manticore manticore-columnar-lib
sudo systemctl start manticore- 从 https://manticoresearch.com/install/ 下载 Windows 压缩包
- 将压缩包中的所有文件解压到
C:\Manticore - 运行以下命令将 Manticore 安装为服务:
-
C:\Manticore\bin\searchd --install --config C:\Manticore\sphinx.conf.in --servicename Manticore - 通过 Microsoft 管理控制台的“服务”管理单元启动 Manticore。
brew install manticoresearch
brew services start manticoresearchdocker pull manticoresearch/manticore
docker run --name manticore -p9306:9306 -p9308:9308 -p9312:9312 -d manticoresearch/manticore要持久化您的数据目录,请阅读 如何在生产环境中使用 Manticore docker
默认情况下,Manticore 在以下端口等待您的连接:
- 端口 9306 用于 MySQL 客户端
- 端口 9308 用于 HTTP/HTTPS 连接
- 端口 9312 用于其他 Manticore 节点和基于 Manticore 二进制 API 的客户端连接
有关 HTTPS 支持的更多详细信息,请参阅我们的学习课程 此处。
- SQL
- HTTP
- PHP
- Python
- Python-asyncio
- Javascript
- Java
- C#
- Rust
- Typescript
- Go
mysql -h0 -P9306HTTP 是无状态协议,因此不需要任何特殊的连接阶段。您可以直接向服务器发送 HTTP 请求并接收响应。要通过 JSON 接口与 Manticore 通信,您可以使用您选择的编程语言中的任何 HTTP 客户端库向服务器发送 GET 或 POST 请求,并解析 JSON 响应:
curl -s "http://localhost:9308/search"// https://github.com/manticoresoftware/manticoresearch-php
require_once __DIR__ . '/vendor/autoload.php';
$config = ['host'=>'127.0.0.1','port'=>9308];
$client = new \Manticoresearch\Client($config);// https://github.com/manticoresoftware/manticoresearch-python
import manticoresearch
config = manticoresearch.Configuration(
host = "http://127.0.0.1:9308"
)
client = manticoresearch.ApiClient(config)
indexApi = manticoresearch.IndexApi(client)
searchApi = manticoresearch.SearchApi(client)
utilsApi = manticoresearch.UtilsApi(client)// https://github.com/manticoresoftware/manticoresearch-python-asyncio
import manticoresearch
config = manticoresearch.Configuration(
host = "http://127.0.0.1:9308"
)
async with manticoresearch.ApiClient(config) as client:
indexApi = manticoresearch.IndexApi(client)
searchApi = manticoresearch.searchApi(client)
utilsApi = manticoresearch.UtilsApi(client)// https://github.com/manticoresoftware/manticoresearch-javascript
var Manticoresearch = require('manticoresearch');
var client= new Manticoresearch.ApiClient()
client.basePath="http://127.0.0.1:9308";
indexApi = new Manticoresearch.IndexApi(client);
searchApi = new Manticoresearch.SearchApi(client);
utilsApi = new Manticoresearch.UtilsApi(client);// https://github.com/manticoresoftware/manticoresearch-java
import com.manticoresearch.client.*;
import com.manticoresearch.client.model.*;
import com.manticoresearch.client.api.*;
...
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("http://127.0.0.1:9308");
...
IndexApi indexApi = new IndexApi(client);
SearchApi searchApi = new UtilsApi(client);
UtilsApi utilsApi = new UtilsApi(client);// https://github.com/manticoresoftware/manticoresearch-net
using System.Net.Http;
...
using ManticoreSearch.Client;
using ManticoreSearch.Api;
using ManticoreSearch.Model;
...
config = new Configuration();
config.BasePath = "http://localhost:9308";
httpClient = new HttpClient();
httpClientHandler = new HttpClientHandler();
...
var indexApi = new IndexApi(httpClient, config, httpClientHandler);
var searchApi = new SearchApi(httpClient, config, httpClientHandler);
var utilsApi = new UtilsApi(httpClient, config, httpClientHandler);// https://github.com/manticoresoftware/manticoresearch-rust
use std::sync::Arc;
use manticoresearch::{
apis::{
{configuration::Configuration,IndexApi,IndexApiClient,SearchApi,SearchApiClient,UtilsApi,UtilsApiClient}
},
};
async fn maticore_connect {
let configuration = Configuration {
base_path: "http://127.0.0.1:9308".to_owned(),
..Default::default(),
};
let api_config = Arc::new(configuration);
let utils_api = UtilsApiClient::new(api_config.clone());
let index_api = IndexApiClient::new(api_config.clone());
let search_api = SearchApiClient::new(api_config.clone());import {
Configuration,
IndexApi,
SearchApi,
UtilsApi
} from "manticoresearch-ts";
...
const config = new Configuration({
basePath: 'http://localhost:9308',
})
const indexApi = new IndexApi(config);
const searchApi = new SearchApi(config);
const utilsApi = new UtilsApi(config);import (
"context"
manticoreclient "github.com/manticoresoftware/manticoresearch-go"
)
...
configuration := manticoreclient.NewConfiguration()
configuration.Servers[0].URL = "http://localhost:9308"
apiClient := manticoreclient.NewAPIClient(configuration)现在让我们创建一个名为 "products" 的表,包含 2 个字段:
- title - 全文字段,将包含我们的产品标题
- price - 类型为 "float" 的字段
请注意,可以省略使用显式创建语句来创建表。有关更多信息,请参阅 自动模式。
有关创建表的不同方法的更多信息,请参阅我们的学习课程:
- SQL
- HTTP
- PHP
- Python
- Python-asyncio
- Javascript
- Java
- C#
- Rust
- TypeScript
- Go
create table products(title text, price float) morphology='stem_en';POST /cli -d "create table products(title text, price float) morphology='stem_en'"$index = new \Manticoresearch\Index($client);
$index->setName('products');
$index->create([
'title'=>['type'=>'text'],
'price'=>['type'=>'float'],
],['morphology' => 'stem_en']);utilsApi.sql('create table products(title text, price float) morphology=\'stem_en\'')await utilsApi.sql('create table products(title text, price float) morphology=\'stem_en\'')res = await utilsApi.sql('create table products(title text, price float) morphology=\'stem_en\'');utilsApi.sql("create table products(title text, price float) morphology='stem_en'", true);utilsApi.Sql("create table products(title text, price float) morphology='stem_en'", true);utils_api.sql("create table products(title text, price float) morphology='stem_en'", Some(true)).await;res = await utilsApi.sql('create table products(title text, price float) morphology=\'stem_en\'');res := apiClient.UtilsAPI.Sql(context.Background()).Body("create table products(title text, price float) morphology='stem_en'").Execute();Query OK, 0 rows affected (0.02 sec){
"total":0,
"error":"",
"warning":""
}- SQL
- JSON
- PHP
- Python
- Python-asyncio
- Javascript
- Java
- C#
- Rust
- TypeScript
- Go
insert into products(title,price) values ('Crossbody Bag with Tassel', 19.85), ('microfiber sheet set', 19.99), ('Pet Hair Remover Glove', 7.99);"id":0 或没有 id 会强制自动 ID 生成。
POST /insert
{
"table":"products",
"doc":
{
"title" : "Crossbody Bag with Tassel",
"price" : 19.85
}
}
POST /insert
{
"table":"products",
"doc":
{
"title" : "microfiber sheet set",
"price" : 19.99
}
}
POST /insert
{
"table":"products",
"doc":
{
"title" : "Pet Hair Remover Glove",
"price" : 7.99
}
}$index->addDocuments([
['title' => 'Crossbody Bag with Tassel', 'price' => 19.85],
['title' => 'microfiber sheet set', 'price' => 19.99],
['title' => 'Pet Hair Remover Glove', 'price' => 7.99]
]);indexApi.insert({"table" : "products", "doc" : {"title" : "Crossbody Bag with Tassel", "price" : 19.85}})
indexApi.insert({"table" : "products", "doc" : {"title" : "microfiber sheet set", "price" : 19.99}})
indexApi.insert({"table" : "products", "doc" : {"title" : "Pet Hair Remover Glove", "price" : 7.99}})await indexApi.insert({"table" : "products", "doc" : {"title" : "Crossbody Bag with Tassel", "price" : 19.85}})
await indexApi.insert({"table" : "products", "doc" : {"title" : "microfiber sheet set", "price" : 19.99}})
await indexApi.insert({"table" : "products", "doc" : {"title" : "Pet Hair Remover Glove", "price" : 7.99}})res = await indexApi.insert({"table" : "products", "doc" : {"title" : "Crossbody Bag with Tassel", "price" : 19.85}});
res = await indexApi.insert({"table" : "products", "doc" : {"title" : "microfiber sheet set", "price" : 19.99}});
res = await indexApi.insert({"table" : "products", "doc" : {"title" : "Pet Hair Remover Glove", "price" : 7.99}});InsertDocumentRequest newdoc = new InsertDocumentRequest();
HashMap<String,Object> doc = new HashMap<String,Object>(){{
put("title","Crossbody Bag with Tassel");
put("price",19.85);
}};
newdoc.index("products").setDoc(doc);
sqlresult = indexApi.insert(newdoc);
newdoc = new InsertDocumentRequest();
doc = new HashMap<String,Object>(){{
put("title","microfiber sheet set");
put("price",19.99);
}};
newdoc.index("products").setDoc(doc);
sqlresult = indexApi.insert(newdoc);
newdoc = new InsertDocumentRequest();
doc = new HashMap<String,Object>(){{
put("title","Pet Hair Remover Glove");
put("price",7.99);
}};
newdoc.index("products").setDoc(doc);
indexApi.insert(newdoc);Dictionary<string, Object> doc = new Dictionary<string, Object>();
doc.Add("title","Crossbody Bag with Tassel");
doc.Add("price",19.85);
InsertDocumentRequest insertDocumentRequest = new InsertDocumentRequest(index: "products", doc: doc);
sqlresult = indexApi.Insert(insertDocumentRequest);
doc = new Dictionary<string, Object>();
doc.Add("title","microfiber sheet set");
doc.Add("price",19.99);
insertDocumentRequest = new InsertDocumentRequest(index: "products", doc: doc);
sqlresult = indexApi.Insert(insertDocumentRequest);
doc = new Dictionary<string, Object>();
doc.Add("title","Pet Hair Remover Glove");
doc.Add("price",7.99);
insertDocumentRequest = new InsertDocumentRequest(index: "products", doc: doc);
sqlresult = indexApi.Insert(insertDocumentRequest);let mut doc1 = HashMap::new();
doc1.insert("title".to_string(), serde_json::json!("Crossbody Bag with Tassel"));
doc1.insert("price".to_string(), serde_json::json!(19.85));
let insert_req1 = InsertDocumentRequest::new("products".to_string(), serde_json::json!(doc1));
let insert_res1 = index_api.insert(insert_req1).await;
let mut doc2 = HashMap::new();
doc2.insert("title".to_string(), serde_json::json!("microfiber sheet set"));
doc2.insert("price".to_string(), serde_json::json!(19.99));
let insert_req2 = InsertDocumentRequest::new("products".to_string(), serde_json::json!(doc2));
let insert_res2 = index_api.insert(insert_req2).await;
let mut doc3 = HashMap::new();
doc3.insert("title".to_string(), serde_json::json!("Pet Hair Remover Glove"));
doc3.insert("price".to_string(), serde_json::json!(7.99));
let insert_req3 = InsertDocumentRequest::new("products".to_string(), serde_json::json!(doc3));
let insert_res3 = index_api.insert(insert_req3).await;res = await indexApi.insert({
index: 'test',
id: 1,
doc: { content: 'Text 1', name: 'Doc 1', cat: 1 },
});
res = await indexApi.insert({
index: 'test',
id: 2,
doc: { content: 'Text 2', name: 'Doc 2', cat: 2 },
});
res = await indexApi.insert({
index: 'test',
id: 3,
doc: { content: 'Text 3', name: 'Doc 3', cat: 7 },
});indexDoc := map[string]interface{} {"content": "Text 1", "name": "Doc 1", "cat": 1 }
indexReq := manticoreclient.NewInsertDocumentRequest("products", indexDoc)
indexReq.SetId(1)
apiClient.IndexAPI.Insert(context.Background()).InsertDocumentRequest(*indexReq).Execute()
indexDoc = map[string]interface{} {"content": "Text 2", "name": "Doc 3", "cat": 2 }
indexReq = manticoreclient.NewInsertDocumentRequest("products", indexDoc)
indexReq.SetId(2)
apiClient.IndexAPI.Insert(context.Background()).InsertDocumentRequest(*indexReq).Execute()
indexDoc = map[string]interface{} {"content": "Text 3", "name": "Doc 3", "cat": 7 }
indexReq = manticoreclient.NewInsertDocumentRequest("products", indexDoc)
indexReq.SetId(3)
apiClient.IndexAPI.Insert(context.Background()).InsertDocumentRequest(*indexReq).Execute()Query OK, 3 rows affected (0.01 sec){
"table": "products",
"_id": 0,
"created": true,
"result": "created",
"status": 201
}
{
"table": "products",
"_id": 0,
"created": true,
"result": "created",
"status": 201
}
{
"table": "products",
"_id": 0,
"created": true,
"result": "created",
"status": 201
}有关此主题的更多详细信息可以在此处找到:
让我们查找其中一个文档。我们将使用的查询是“remove hair”。如您所见,它找到了一个标题为“Pet Hair Remover Glove”的文档,并在其中突出显示了“Hair remover”,即使查询中使用的是“remove”而不是“remover”。这是因为当我们创建表时,我们启用了英语词干提取(morphology "stem_en")。
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- TypeScript
- Go
select id, highlight(), price from products where match('remove hair');POST /search
{
"table": "products",
"query": { "match": { "title": "remove hair" } },
"highlight":
{
"fields": ["title"]
}
}$result = $index->search('@title remove hair')->highlight(['title'])->get();
foreach($result as $doc)
{
echo "Doc ID: ".$doc->getId()."\n";
echo "Doc Score: ".$doc->getScore()."\n";
echo "Document fields:\n";
print_r($doc->getData());
echo "Highlights: \n";
print_r($doc->getHighlight());
}searchApi.search({"table":"products","query":{"query_string":"@title remove hair"},"highlight":{"fields":["title"]}})await searchApi.search({"table":"products","query":{"query_string":"@title remove hair"},"highlight":{"fields":["title"]}})res = await searchApi.search({"table":"products","query":{"query_string":"@title remove hair"}"highlight":{"fields":["title"]}});query = new HashMap<String,Object>();
query.put("query_string","@title remove hair");
searchRequest = new SearchRequest();
searchRequest.setIndex("forum");
searchRequest.setQuery(query);
HashMap<String,Object> highlight = new HashMap<String,Object>(){{
put("fields",new String[] {"title"});
}};
searchRequest.setHighlight(highlight);
searchResponse = searchApi.search(searchRequest);object query = new { query_string="@title remove hair" };
var searchRequest = new SearchRequest("products", query);
var highlight = new Highlight();
highlight.Fieldnames = new List<string> {"title"};
searchRequest.Highlight = highlight;
searchResponse = searchApi.Search(searchRequest);let query = SearchQuery {
query_string: Some(serde_json::json!("@title remove hair").into()),
..Default::default()
};
let highlight = Highlight {
fields: Some(serde_json::json!(["title"]).into()),
..Default::default()
};
let search_req = SearchRequest {
table: "products".to_string(),
query: Some(Box::new(query)),
highlight: Some(Box::new(highlight)),
..Default::default(),
};
let search_res = search_api.search(search_req).await;res = await searchApi.search({
index: 'test',
query: { query_string: {'text 1'} },
highlight: {'fields': ['content'] }
});searchRequest := manticoreclient.NewSearchRequest("test")
query := map[string]interface{} {"query_string": "text 1"};
searchRequest.SetQuery(query);
highlightField := manticoreclient.NewHighlightField("content")
fields := []interface{}{ highlightField }
highlight := manticoreclient.NewHighlight()
highlight.SetFields(fields)
searchRequest.SetHighlight(highlight);
res, _, _ := apiClient.SearchAPI.Search(context.Background()).SearchRequest(*searchRequest).Execute()+---------------------+-------------------------------+----------+
| id | highlight() | price |
+---------------------+-------------------------------+----------+
| 1513686608316989452 | Pet <b>Hair Remover</b> Glove | 7.990000 |
+---------------------+-------------------------------+----------+
1 row in set (0.00 sec){
"took": 0,
"timed_out": false,
"hits": {
"total": 1,
"hits": [
{
"_id": 1513686608316989452,
"_score": 1680,
"_source": {
"price": 7.99,
"title": "Pet Hair Remover Glove"
},
"highlight": {
"title": [
"Pet <b>Hair Remover</b> Glove"
]
}
}
]
}
}Doc ID: 1513686608316989452
Doc Score: 1680
Document fields:
Array
(
[price] => 7.99
[title] => Pet Hair Remover Glove
)
Highlights:
Array
(
[title] => Array
(
[0] => Pet <b>Hair Remover</b> Glove
)
)`
{'hits': {'hits': [{u'_id': u'1513686608316989452',
u'_score': 1680,
u'_source': {u'title': u'Pet Hair Remover Glove', u'price':7.99},
u'highlight':{u'title':[u'Pet <b>Hair Remover</b> Glove']}}}],
'total': 1},
'profile': None,
'timed_out': False,
'took': 0}{'hits': {'hits': [{u'_id': u'1513686608316989452',
u'_score': 1680,
u'_source': {u'title': u'Pet Hair Remover Glove', u'price':7.99},
u'highlight':{u'title':[u'Pet <b>Hair Remover</b> Glove']}}}],
'total': 1},
'profile': None,
'timed_out': False,
'took': 0}{"hits": {"hits": [{"_id": 1513686608316989452,
"_score": 1680,
"_source": {"title": "Pet Hair Remover Glove", "price":7.99},
"highlight":{"title":["Pet <b>Hair Remover</b> Glove"]}}],
"total": 1},
"profile": None,
"timed_out": False,
"took": 0}class SearchResponse {
took: 84
timedOut: false
hits: class SearchResponseHits {
total: 1
maxScore: null
hits: [{_id=1513686608316989452, _score=1, _source={price=7.99, title=Pet Hair Remover Glove}, highlight={title=[Pet <b>Hair Remover</b> Glove]}}]
aggregations: null
}
profile: null
}class SearchResponse {
took: 103
timedOut: false
hits: class SearchResponseHits {
total: 1
maxScore: null
hits: [{_id=1513686608316989452, _score=1, _source={price=7.99, title=Pet Hair Remover Glove}, highlight={title=[Pet <b>Hair Remover</b> Glove]}}]
aggregations: null
}
profile: null
}class SearchResponse {
took: 103
timedOut: false
hits: class SearchResponseHits {
total: 1
maxScore: null
hits: [{_id=1513686608316989452, _score=1, _source={price=7.99, title=Pet Hair Remover Glove}, highlight={title=[Pet <b>Hair Remover</b> Glove]}}]
aggregations: null
}
profile: null
}{
"hits":
{
"hits":
[{
"_id": 1,
"_score": 1400,
"_source": {"content":"Text 1","name":"Doc 1","cat":1},
"highlight": {"content":["<b>Text 1</b>"]}
}],
"total": 1
},
"profile": None,
"timed_out": False,
"took": 0
}{
"hits":
{
"hits":
[{
"_id": 1,
"_score": 1400,
"_source": {"content":"Text 1","name":"Doc 1","cat":1},
"highlight": {"content":["<b>Text 1</b>"]}
}],
"total": 1
},
"profile": None,
"timed_out": False,
"took": 0
}有关Manticore中可用的不同搜索选项的更多信息,可以在我们的学习课程中找到:
- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- TypeScript
- Go
update products set price=18.5 where id = 1513686608316989452;POST /update
{
"table": "products",
"id": 1513686608316989452,
"doc":
{
"price": 18.5
}
}$doc = [
'body' => [
'table' => 'products',
'id' => 2,
'doc' => [
'price' => 18.5
]
]
];
$response = $client->update($doc);indexApi = api = manticoresearch.IndexApi(client)
indexApi.update({"table" : "products", "id" : 1513686608316989452, "doc" : {"price":18.5}})indexApi = api = manticoresearch.IndexApi(client)
await indexApi.update({"table" : "products", "id" : 1513686608316989452, "doc" : {"price":18.5}})res = await indexApi.update({"table" : "products", "id" : 1513686608316989452, "doc" : {"price":18.5}});UpdateDocumentRequest updateRequest = new UpdateDocumentRequest();
doc = new HashMap<String,Object >(){{
put("price",18.5);
}};
updateRequest.index("products").id(1513686608316989452L).setDoc(doc);
indexApi.update(updateRequest);Dictionary<string, Object> doc = new Dictionary<string, Object>();
doc.Add("price", 18.5);
UpdateDocumentRequest updateDocumentRequest = new UpdateDocumentRequest(index: "products", id: 1513686608316989452L, doc: doc);
indexApi.Update(updateDocumentRequest);let mut doc = HashMap::new();
doc.insert("price".to_string(), serde_json::json!(18.5));
let update_req = UpdateDocumentRequest {
table: serde_json::json!("products"),
doc: serde_json::json!(doc),
id: serde_json::json!(1513686608316989452),
..Default::default(),
};
let update_res = index_api.update(update_req).await;res = await indexApi.update({ index: "test", id: 1, doc: { cat: 10 } });updDoc = map[string]interface{} {"cat": 10}
updRequest = manticoreclient.NewUpdateDocumentRequest("test", updDoc)
updRequest.SetId(1)
res, _, _ = apiClient.IndexAPI.Update(context.Background()).UpdateDocumentRequest(*updRequest).Execute()Query OK, 1 row affected (0.00 sec){
"table": "products",
"_id": 1513686608316989452,
"result": "updated"
}- SQL
- JSON
- PHP
- Python
- Python-asyncio
- javascript
- Java
- C#
- Rust
- TypeScript
- Go
delete from products where price < 10;POST /delete
{
"table": "products",
"query":
{
"range":
{
"price":
{
"lte": 10
}
}
}
}$result = $index->deleteDocuments(new \Manticoresearch\Query\Range('price',['lte'=>10]));indexApi.delete({"table" : "products", "query": {"range":{"price":{"lte":10}}}})await indexApi.delete({"table" : "products", "query": {"range":{"price":{"lte":10}}}})res = await indexApi.delete({"table" : "products", "query": {"range":{"price":{"lte":10}}}});DeleteDocumentRequest deleteRequest = new DeleteDocumentRequest();
query = new HashMap<String,Object>();
query.put("range",new HashMap<String,Object>(){{
put("price",new HashMap<String,Object>(){{
put("lte",10);
}});
}});
deleteRequest.index("products").setQuery(query);
indexApi.delete(deleteRequest);Dictionary<string, Object> price = new Dictionary<string, Object>();
price.Add("lte", 10);
Dictionary<string, Object> range = new Dictionary<string, Object>();
range.Add("price", price);
DeleteDocumentRequest deleteDocumentRequest = new DeleteDocumentRequest(index: "products", query: range);
indexApi.Delete(deleteDocumentRequest);let mut price_range= HashMap::new();
price_range.insert("lte".to_string(), serde_json::json!(10));
let mut range= HashMap::new();
range.insert("price".to_string(), serde_json::json!(price_range));
let delete_req = DeleteDocumentRequest {
table: "products".to_string(),
query: serde_json::json!(range),
..Default::default(),
};
index_api.delete(delete_req).await;res = await indexApi.delete({
index: 'test',
query: { match: { '*': 'Text 1' } },
});delRequest := manticoreclient.NewDeleteDocumentRequest("test")
matchExpr := map[string]interface{} {"*": "Text 1t"}
delQuery := map[string]interface{} {"match": matchExpr }
delRequest.SetQuery(delQuery)
res, _, _ := apiClient.IndexAPI.Delete(context.Background()).DeleteDocumentRequest(*delRequest).Execute();Query OK, 1 row affected (0.00 sec){
"table": "products",
"deleted": 1
}Array
(
[_index] => products
[deleted] => 1
)安装后,Manticore Search 服务不会自动启动。要启动 Manticore,请运行以下命令:
sudo systemctl start manticore
要停止 Manticore,请运行以下命令:
sudo systemctl stop manticore
Manticore 服务设置为开机启动。你可以通过运行以下命令来检查:
sudo systemctl is-enabled manticore
如果你想禁止 Manticore 在开机时启动,运行:
sudo systemctl disable manticore
要使 Manticore 在开机时启动,运行:
sudo systemctl enable manticore
searchd 进程将启动信息记录在 systemd 日志中。如果启用了 systemd 日志记录,你可以使用以下命令查看日志信息:
sudo journalctl -u manticore
systemctl set-environment _ADDITIONAL_SEARCHD_PARAMS 允许你指定自定义启动参数,用于启动 Manticore Search 守护进程。完整列表请参见 这里。
例如,要以调试日志级别启动 Manticore,你可以运行:
systemctl set-environment _ADDITIONAL_SEARCHD_PARAMS='--logdebug'
systemctl restart manticore
要撤销该设置,运行:
systemctl set-environment _ADDITIONAL_SEARCHD_PARAMS=''
systemctl restart manticore
注意,systemd 环境变量在服务器重启时会被重置。
Manticore 可以使用 service 命令来启动和停止:
sudo service manticore start
sudo service manticore stop
要在 RedHat 系统上启用 sysV 服务开机自启动,运行:
chkconfig manticore on
要在 Debian 系统(包括 Ubuntu)上启用 sysV 服务开机自启动,运行:
update-rc.d manticore defaults
请注意,searchd 由 init 系统在 manticore 用户下启动,服务器创建的所有文件都归该用户所有。如果 searchd 由例如 root 用户启动,文件权限会被更改,这可能导致再次以服务方式运行 searchd 时出现问题。
您也可以通过直接调用 searchd(Manticore Search 服务器二进制文件)来启动 Manticore Search:
searchd [OPTIONS]
请注意,如果没有指定配置文件的路径,searchd 将会根据操作系统在几个位置尝试查找它。
在所有操作系统中,searchd 可用的选项包括:
-
--help(简写为-h)列出在您当前构建的searchd中可以使用的所有参数。 -
--version(简写为-v)显示 Manticore Search 的版本信息。 -
--quiet(简写为-q)抑制启动输出,仅显示错误(横幅和预加载消息)。 -
--config <file>(简写为-c <file>)告诉searchd使用指定的文件作为其配置。 -
--stop用于异步停止searchd,使用 Manticore 配置文件中指定的 PID 文件详细信息。因此,您可能还需要通过--config选项向searchd确认要使用的配置文件。示例:$ searchd --config /etc/manticoresearch/manticore.conf --stop -
--stopwait用于同步停止searchd。--stop本质上是告诉正在运行的实例退出(通过发送 SIGTERM),然后立即返回。--stopwait还会尝试等待直到正在运行的searchd实例实际完成关闭(例如,保存所有待处理的属性更改)并退出。示例:$ searchd --config /etc/manticoresearch/manticore.conf --stopwait可能的退出代码如下:
- 成功时为 0
- 如果连接到正在运行的 searchd 服务器失败时为 1
- 如果服务器在关闭期间报告错误时为 2
- 如果服务器在关闭期间崩溃时为 3
-
--status命令用于通过配置文件(可选提供)中的连接详细信息查询正在运行的searchd实例状态。它将尝试使用配置文件中找到的第一个 UNIX 套接字或 TCP 端口连接到正在运行的实例。成功时,它将查询多个状态和性能计数器值并打印出来。您也可以使用 SHOW STATUS 命令通过 SQL 协议访问相同的计数器。示例:$ searchd --status $ searchd --config /etc/manticoresearch/manticore.conf --status -
--pidfile用于显式强制使用 PID 文件(其中存储了searchd进程标识号),即使其他调试选项另有说明(例如,--console)。这是一个调试选项。$ searchd --console --pidfile -
--console用于强制searchd进入控制台模式。通常,Manticore 作为常规服务器应用程序运行,并将信息记录到日志文件中(如配置文件中指定)。但是,当调试配置或服务器本身的问题,或尝试诊断难以追踪的问题时,强制它直接将信息转储到调用它的控制台/命令行可能更方便。在控制台模式下运行还意味着进程不会分叉(因此搜索是顺序进行的),并且不会写入日志。(需要注意的是,控制台模式不是运行searchd的预期方法。)您可以这样调用它:$ searchd --config /etc/manticoresearch/manticore.conf --console -
--logdebug、--logreplication、--logdebugv和--logdebugvv选项用于在服务器日志中启用额外的调试输出。它们的区别在于日志详细程度级别。这些是调试选项,通常不应启用,因为它们可能会大量污染日志。它们可以临时启用以协助复杂的调试会话。 -
--iostats与日志选项(manticore.conf中必须已激活query_log)一起使用,以提供有关查询过程中执行的输入/输出操作的更详细信息,这会带来轻微的性能损失和稍大的日志。IO 统计信息不包括属性的 IO 操作信息,因为这些是通过 mmap 加载的。要启用它,您可以这样启动searchd:$ searchd --config /etc/manticoresearch/manticore.conf --iostats -
--cpustats用于在查询日志文件(每个查询)和状态报告(聚合)中提供实际的 CPU 时间报告(除了墙时间)。它依赖于 Linux 系统调用clock_gettime(),或者在某些系统上回退到较不精确的调用。您可以这样启动searchd:$ searchd --config /etc/manticoresearch/manticore.conf --cpustats -
--port portnumber(简写为-p)用于指定 Manticore 应监听以接受二进制协议请求的端口,通常用于调试目的。这通常默认为 9312,但有时需要在不同的端口上运行。在命令行上指定它将覆盖配置文件中指定的任何内容。有效范围是 0 到 65535,但 1024 及以下的端口通常需要特权账户才能运行。使用示例:
$ searchd --port 9313 -
--listen ( address ":" port | port | path ) [ ":" protocol ](或-l简写)与--port的作用相同,但允许您指定不仅仅是端口,还可以指定完整的路径、IP 地址和端口,或 Unix 域套接字路径,searchd将监听这些。换句话说,您可以指定 IP 地址(或主机名)和端口号,仅端口号,或 Unix 套接字路径。如果您指定了端口号但未指定地址,searchd 将监听所有网络接口。Unix 路径通过前导斜杠标识。作为最后一个参数,您还可以指定用于此套接字连接的协议处理程序(监听器)。支持的协议值为 'sphinx' 和 'mysql'(自 4.1 版本以来使用的 MySQL 协议)。 -
--force-preread禁止服务器在预读取表文件完成之前服务任何传入连接。默认情况下,在启动时,服务器在表文件懒加载到内存时接受连接。这扩展了该行为,并使其等待直到文件加载完成。 -
--index (--table) <table>(或-i (-t) <table>简写)强制此searchd实例仅服务指定的表。与上面的--port一样,这通常用于调试目的;更长期的更改通常会直接应用于配置文件本身。 -
--strip-path从表中引用的所有文件名(停用词、词形变化、例外等)中剥离路径名。这对于拾取在另一台机器上构建的表(路径布局可能不同)非常有用。 -
--replay-flags=<OPTIONS>开关可用于指定额外的二进制日志重放选项列表。支持的选项有:accept-desc-timestamp,忽略递减的事务时间戳并仍然重放这些事务(默认行为是出现错误时退出)。ignore-open-errors,忽略缺失的二进制日志文件(默认行为是出现错误时退出)。ignore-trx-errors,忽略任何事务错误并跳过当前二进制日志文件(默认行为是出现错误时退出)。ignore-all-errors,忽略上述任何错误(默认行为是出现错误时退出)。
例如:
$ searchd --replay-flags=accept-desc-timestamp -
--coredump用于启用在服务器崩溃时保存核心文件或迷你转储。默认禁用以加快服务器崩溃时的重启速度。这对于调试很有用。$ searchd --config /etc/manticoresearch/manticore.conf --coredump -
--new-cluster启动一个复制集群并使服务器成为带有集群重启保护的参考节点。在 Linux 上你还可以运行manticore_new_cluster。它将通过 systemd 以--new-cluster模式启动 Manticore。 -
--new-cluster-force启动一个复制集群并使服务器成为参考节点,绕过集群重启保护。在 Linux 上你还可以运行manticore_new_cluster --force。它将通过 systemd 以--new-cluster-force模式启动 Manticore。 -
--mockstack分析并报告递归表达式求值、模式匹配操作和过滤处理所需的堆栈大小。此调试选项将计算的堆栈需求输出到控制台以进行优化。输出提供了可用于配置不同操作堆栈需求的环境变量。例如:
$ searchd --mockstack Manticore 7.4.7 e90b5afbb@25032706 dev (columnar 4.1.2 15bbcc7@25031206) (secondary 4.1.2 15bbcc7@25031206) (knn 4.1.2 15bbcc7@25031206) Copyright (c) 2001-2016, Andrew Aksyonoff Copyright (c) 2008-2016, Sphinx Technologies Inc (http://sphinxsearch.com) Copyright (c) 2017-2025, Manticore Software LTD (https://manticoresearch.com) export MANTICORE_KNOWN_CREATE_SIZE=200 export MANTICORE_START_KNOWN_CREATE_SIZE=4504 export MANTICORE_KNOWN_EXPR_SIZE=16 export MANTICORE_START_KNOWN_EXPR_SIZE=200 export MANTICORE_NONE=32 export MANTICORE_START_NONE=104 export MANTICORE_KNOWN_FILTER_SIZE=224 export MANTICORE_START_KNOWN_FILTER_SIZE=11192 export MANTICORE_KNOWN_MATCH_SIZE=320 export MANTICORE_START_KNOWN_MATCH_SIZE=14552 export NO_STACK_CALCULATION=1
searchd 在 Windows 平台上有一些特定的选项,主要是关于作为服务的处理,仅在 Windows 二进制文件上可用。
请注意,Windows 平台上的 searchd 默认使用 --console 模式,除非你将其安装为服务。
-
--install将searchd安装为 Microsoft 管理控制台(控制面板 / 管理工具 / 服务)中的服务。命令行中除--install外指定的其它参数也将成为服务未来启动时命令行的一部分。例如,作为调用searchd的一部分,你可能还需要使用--config指定配置文件,这时也应该与--install一起指定。调用后,可以通过管理控制台使用常规的启动/停止功能,因此任何启动、停止和重启服务的方法也适用于searchd。示例:C:\WINDOWS\system32> C:\Manticore\bin\searchd.exe --install --config C:\Manticore\manticore.conf如果你希望每次启动
searchd都显示 I/O 统计,需要将该选项与--install命令在同一行指定,如下:C:\WINDOWS\system32> C:\Manticore\bin\searchd.exe --install --config C:\Manticore\manticore.conf --iostats -
--delete从 Microsoft 管理控制台及服务注册的其它位置移除该服务,前提是之前使用了--install。注意,这不会卸载软件或删除表。它意味着服务将不会被服务系统调用,也不会在机器下一次启动时启动。如果当前作为服务运行,当前实例不会被终止(直到下一次重启或使用--stop)。如果服务是用自定义名称(通过--servicename)安装的,卸载时也需要使用相同的名称指定--servicename。示例:C:\WINDOWS\system32> C:\Manticore\bin\searchd.exe --delete -
--servicename <name>在安装或删除服务时赋予searchd一个名字,这个名字将显示在管理控制台;默认是 searchd,但如果在多管理员登录的服务器,或有多个searchd实例的系统上部署,可能需要更具描述性的名字。注意,除非与--install或--delete结合使用,否则此选项无效。示例:C:\WINDOWS\system32> C:\Manticore\bin\searchd.exe --install --config C:\Manticore\manticore.conf --servicename ManticoreSearch -
--ntservice是由 Microsoft 管理控制台传递给searchd的选项,用于在 Windows 平台以服务形式调用它。通常不需要直接调用此选项;这是 Windows 启动服务时自动调用的,但理论上你可以作为命令行中的常规服务调用它(作为--console的补充)。 -
--safetrace强制searchd在崩溃报告中仅使用系统的 backtrace() 调用。在某些(罕见)场景中,这可能是获取报告的“更安全”方式。这是一个调试选项。 -
--nodetach开关(仅限 Linux)告诉searchd不要分离到后台。这也会导致日志条目打印到控制台。查询处理照常进行。这是一个调试选项,也可能在你运行 Manticore 容器化时捕获输出时有用。
Manticore 利用 plugin_dir 来存储和使用 Manticore Buddy 插件。默认情况下,该值在标准安装中对 “manticore” 用户可访问。但是,如果你以不同用户手动启动 searchd 守护进程,守护进程可能无法访问 plugin_dir。为解决此问题,请确保在公共配置章节指定一个搜索守护进程运行用户可写的 plugin_dir。
searchd 支持多个信号:
SIGTERM- 初始清理关闭。新查询将不会被处理,但已启动的查询不会被强制中断。SIGHUP- 启动表的旋转。根据 seamless_rotate 设置值,新查询可能会短暂卡住;客户端将收到临时错误。SIGUSR1- 强制重开搜索d日志和查询日志文件,允许日志文件旋转。
MANTICORE_TRACK_DAEMON_SHUTDOWN=1启用详细日志,当搜索d关闭时会记录详细信息。这在某些关闭问题中非常有用,例如当Manticore长时间关闭或在关闭过程中冻结时。