前言
首先,我想說的是,看官方文檔很重要,雖然可能都是英文,并且也很長(zhǎng),但是基本都很有用。
普通索引
不多介紹,一搜一大把,簡(jiǎn)要介紹可以看菜鳥教程
文本索引
之前在進(jìn)行文本匹配時(shí)候,用的是正則$regex,后來發(fā)現(xiàn)mongo自帶有一個(gè)文本索引,所以就研究了下
首先上官方文檔,這里有一個(gè)中文版本的,但是中文版本缺少內(nèi)容。可以先看中文版,然后補(bǔ)充看英文版
簡(jiǎn)要說明一下重點(diǎn)(用了中文版本中的例子)
建立索引
db.stores.createIndex( { name: "text", description: "text" } )
find操作
db.stores.find( { $text: { $search: "java coffee shop" } } )
注意,上面匹配到的是只要包含java coffee shop中至少一個(gè)詞就返回結(jié)果,否則用精確搜索
精確索引(這一點(diǎn)在后面會(huì)補(bǔ)充)
db.stores.find( { $text: { $search: "java \"coffee shop\"" } } )
詞語排除
db.stores.find( { $text: { $search: "java shop -coffee" } } )
排序
db.stores.find(
{ $text: { $search: "java coffee shop" } },
{ score: { $meta: "textScore" } }
).sort( { score: { $meta: "textScore" } } )
根據(jù)英文版本補(bǔ)充
首先,在find時(shí)候有額外的幾個(gè)參數(shù)可選,
{
$text:
{
$search: <string>,
$language: <string>,
$caseSensitive: <boolean>,
$diacriticSensitive: <boolean>
}
}
大小寫敏感$caseSensitive,默認(rèn)是false
發(fā)音敏感$diacriticSensitive,默認(rèn)是false。這個(gè)要說明一下,搜索發(fā)現(xiàn)具體解釋可以看此處,簡(jiǎn)單說就是,如果不敏感,那么As such, the index also does not distinguish between é, é, e, and E.
限制
挑幾個(gè)說,具體還是看英文文檔去
- A query can specify, at most, one
$textexpression.
這一點(diǎn)的話,我當(dāng)時(shí)想搜索同時(shí)匹配兩個(gè)詞的情況,在Robo 3Tfind里面用多個(gè)沒問題,但是后來在程序里面pymongo就遇到了問題,但是后來發(fā)現(xiàn)沒有必要,下文會(huì)解釋
如果用在aggregation里面
- The
$matchstage that includes a$textmust be the first stage in the pipeline. - A text operator can only occur once in the stage.
- The text search, by default, does not return the matching documents in order of matching scores. Use the
$metaaggregation expression in the$sortstage.
否定詞
- A hyphenated word, such as
pre-market, is not a negation. If used in a hyphenated word,$textoperator treats the hyphen-minus (-) as a delimiter. To negate the wordmarketin this instance, include a space betweenpreand-market, i.e.,pre -market.
連字符詞,如pre-market,不是否定詞。如果在帶連字符的單詞中使用,$text操作符將連字符-(-)作為分隔符。要在本例中否定market一詞,請(qǐng)?jiān)?code>pre和-market之間加上空格,即pre -market。
關(guān)于這一點(diǎn),我也有一點(diǎn)想補(bǔ)充說
在最后使用時(shí)發(fā)現(xiàn),當(dāng)搜索hand時(shí)候,如果文本中有hand-helds也會(huì)被搜索到,但是handhelds不會(huì),那是不是和這個(gè)-相關(guān)呢?待考證
所以在使用時(shí)需要注意上面這個(gè)細(xì)節(jié)
另外
Stop Words
- 會(huì)自動(dòng)去掉Stop Words
The$textoperator ignores language-specific stop words, such astheandandin English.
Stemmed Words
- 詞根 (居然能自動(dòng)實(shí)現(xiàn))
For case insensitive and diacritic insensitive(前提) text searches, the$textoperator matches on the complete stemmed word. So if a document field contains the wordblueberry, a search on the termbluewill not match. However,blueberryorblueberrieswill match.
注意:mongo會(huì)自動(dòng)將text的內(nèi)容以及find中的query都進(jìn)行stemmed處理
補(bǔ)充精確搜索(同時(shí)包含多個(gè)詞)
上面說到,當(dāng)時(shí)我想搜索同時(shí)包含兩個(gè)詞(eg:java coffee shop)的文檔,如果用db.stores.find( { $text: { $search: "java coffee shop" } } )得到的是至少包含一個(gè)詞的結(jié)果
所以一開始我想用db.stores.find( { $text: { $search: "java" }, $text: { $search: "coffee" } } )這樣
在robo上可行,但是在pymongo里面不可行(上面文檔也說不行)
后來發(fā)現(xiàn)直接db.stores.find( { $text: { $search: "\"java\" \"coffee\" \"shop\"" } } )這樣就夠了,反斜杠只是為了區(qū)分引號(hào)
而在python里面可以通過單雙引號(hào)來實(shí)現(xiàn)
que_str = ''
for que in filtered_query: #對(duì)于text索引的多條件
que_str += '"' + que + '"'
con.append({'$text':{'$search':que_str}})
補(bǔ)充參考
https://docs.mongodb.com/manual/core/index-text/ 這個(gè)好像是index-text的介紹