Mongo Shell 文档搜索

Mongo Shell 文档搜索

  • MongoDB支持执行字符串内容的文本搜索的查询操作,通过文本索引和 $text 运算符实现。
  • $text
  • 文本搜索

练习用到的数据:

  db.stores.insert(
          [
              { _id: 1, name: "Java Hut", description: "Coffee and cakes" },
              { _id: 2, name: "Burger Buns", description: "Gourmet hamburgers" },
              { _id: 3, name: "Coffee Shop", description: "Just coffee" },  
              { _id: 4, name: "Clothes Clothes Clothes", description: "Discount clothing" }, 
              { _id: 5, name: "Java Shopping", description: "Indonesian goods" } 
          ]
  )

文字索引

  • MongoDB提供了文本索引来对字符串内容的文本查询搜索,文本索引可以包含值为字符串或者字符串元素数组的任何字段。

  • 如果要在集合上执行文档搜索,则集合必须存在文档索引;每一个集合最多只能有一个文档索引,但是文档索引可以覆盖多个字段。

  • 例如,在mongo shell执行下面的语句:

    db.stores.createIndex( { name: "text", description: "text" } )
    

    会给集合 stores 创建文档索引,该文档索引包含了两个字段 namedescription

$text运算符

使用 $text 运算符可以对拥有文档索引的集合执行文档搜索操作;

一般查询

$text 可以使用空格和大多数标点作为分隔符对搜索字符串进行标记,并在搜索字符串中对所有这些标记进行逻辑或者操作;

建立了文档索引的字段,如果任意一个字段包含了查询条件中的任意一个术语,那么该文档即是满足查询条件的

例如,下面的语句可以在集合中查找包含"cofee" “java” 和 "shop"列表中任何术语的集合文档:

db.stores.find( { $text: { $search: "java coffee shop" } } )
>>>
[
{ _id: 1, name: "Java Hut", description: "Coffee and cakes" },
{ _id: 3, name: "Coffee Shop", description: "Just coffee" },  
{ _id: 5, name: "Java Shopping", description: "Indonesian goods" } 
 ]

准确查询

可以通过将作为查询条件的短语或单个术语包装在双引号中来实现精准查询,如果 $search 的字符串中只包含一个被双引号修饰的短语或单个术语,文本搜索将只匹配文档索引字段的值等于该短语或者单个术语的文档。

db.stores.find( { $text: { $search: "\"coffee shop\"" } } )
>>>
[{ _id: 3, name: "Coffee Shop", description: "Just coffee" },]

期限排除

在需要排除的术语前面加一个 - 符号,则文档搜索将匹配不包含此术语的文档;

db.stores.find( { $text: { $search: "java shop -coffee" } } )
>>>
[
{ _id: 5, name: "Java Shopping", description: "Indonesian goods" } 
]

如果查询条件,即 $search的字符串中只有一个包含否定词的搜索字符串,那么文档索引将不会匹配任何文档,即:

db.stores.find( { $text: { $search: "-coffee" } } )
>>>
None

如果查询字符串中有连字符的词,例如 pre-process$text并不会将连字符视为否定符号,如果要否定带有连字符的术语(以pre-process为例),需要在pre-process之间插入一个空格,即 pre -process

排序

默认情况下,MongoDB查询的返回数据以无序的方式返回,但是文档搜索会为每个文档计算一个相关性分数,即该文档与搜索字符串的相关程度,计算相关性分数需要 $meta 运算符。

db.stores.find( 
      { $text: { $search: "java coffee shop" } },
      { score: { $meta: "textScore" } }
  ).sort( { score: -1 } )
>>>
[
{ _id: 3, name: "Coffee Shop", description: "Just coffee", "score":2.25},  
{ _id: 5, name: "Java Shopping", description: "Indonesian goods", "score":1.5 },
{ _id: 1, name: "Java Hut", description: "Coffee and cakes", "score":1.5 }
]

在计算相关性分数的时候,*** m e t a ∗ ∗ ∗ 的 值 固 定 为 " t e x t S c o r e " , 具 体 用 法 可 以 看 [ meta***的值固定为 "textScore",具体用法可以看 [ meta"textScore"[meta](https://www.mongodb.com/docs/manual/reference/operator/aggregation/meta/#mongodb-expression-exp.-meta);上面的查询语句是find语句结束后,查询的信息里面多了一个字段score,然后再根据score排下序。

$text的限制

$text的限制

$text操作符的使用有一些限制条件:

  • 一个查询中最多指定一个$text表达式;
  • t e x t 不 能 出 现 在 text不能出现在 textnor表达式中;
  • t e x t 不 能 出 现 在 text不能出现在 texteleMatch表达式中;
  • 如果在 o r 表 达 式 中 使 用 or表达式中使用 or使text,则$or的数组中每一个子句都必须被索引

聚合管道

文档搜索也可以用在聚合管道中

限制条件

除了 t e x t 本 身 的 限 制 , 在 聚 合 管 道 使 用 text本身的限制,在聚合管道使用 text使text也有一些额外的限制:

  • 包含 t e x t 的 语 句 必 须 是 text的语句必须是 textmatch阶段的第一个阶段;
  • $text在管道的阶段中只能出现一次;
  • t e x t 不 能 出 现 在 text不能出现在 textor和$not运算符的表达式中;
  • 默认情况下,文本搜索不会按照顺序返回文档,但是可以在 s o r t 阶 段 通 过 sort阶段通过 sortmeta聚合表达式使文档有序返回。
文字分数

t e x t 操 作 符 为 搜 索 的 每 一 个 文 档 提 供 一 个 分 数 , 分 数 表 示 文 档 与 搜 索 文 本 的 相 关 程 度 , 这 个 分 数 可 用 于 text操作符为搜索的每一个文档提供一个分数,分数表示文档与搜索文本的相关程度,这个分数可用于 textsort阶段进行排序,分数的计算: {$meta: 'textScore'}

db.articles.aggregate(
    [
      { $match: { $text: { $search: "cake tea" } } }, 
      { $sort: { score: { $meta: "textScore" } } }, 
      { $project: { title: 1, _id: 0 } } 
    ]
  )

还可以进行文字分数匹配,即返回相关性高于某数字的文档:

 db.articles.aggregate(
    [
        { $match: { $text: { $search: "cake tea" } } },
        { $project: { title: 1, _id: 0, score: { $meta: "textScore" } } },
        { $match: { score: { $gt: 1.0 } } }
    ]
 )

指定文本搜索的语言:

db.articles.aggregate(
    [   
            { $match: { $text: { $search: "saber -claro", $language: "es" } } }, 
            { $group: { _id: null, views: { $sum: "$views" } } } 
    ]
 )
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值