• nodejs + mongodb实现模糊查询与全文搜索


     

    mongodb中的查询条件

     

     

     

    关键字说明
    $or 或关系
    $nor 或关系取反
    $gt 大于
    $gte 大于等于
    $lt 小于
    $lte 小于等于
    $ne 不等于
    $in 在多个值范围内
    $nin 不在多个值范围内
    $all 匹配数组中多个值
    $regex 正则,用于模糊查询
    $size 匹配数组大小
    $maxDistance 范围查询,距离(基于LBS)
    $mod 取模运算
    $near 邻域查询,查询附近的位置(基于LBS)
    $exists 字段是否存在
    $elemMatch 匹配内数组内的元素
    $within 范围查询(基于LBS)
    $box 范围查询,矩形范围
    $center 范围查询,圆形范围
    $centerSphere 范围查询,球形范围
    $slice 查询字段集合中的元素(比如从第几个之后,第N到第M个元素)

     

    mongodb中的查询语句

    db.movies.find({'name':/未来/})
    db.collection.find( { field: { $regex: 'acme.*corp', $options: 'i' } } );

    官方举例是通过 '/.../' 和$regex,这两种都可以查询到结果。

    现在我想实现查询标题关键字匹配到对应文章。

    如下:

    1.查询title字段中包含某个字符串的集合:

     Article.find({"title":{$regex: /searchValue/,$options:'i'}}, (err, data) => { // {"title": /searchValue/} $options:'i' 表示忽略大小写
            if(err) {
                console.log(err)
                return res.status(500).json({
                    result: 1,
                    error_info: err.message
                })
            }
            console.log(data)
            let length = data.length
            return res.status(200).json({
                result: 0,
                count: length,
                searchArticle: data
            })
        })
    searchValue是前端传过来的查询关键词。

    这么写好像没有问题,跟官方实例一样,但是查询不到结果。

    请注意,MongoDB的的模糊查询是通过正则表达式实现的,对应mongodb中,可以直接使用 ‘/../’ 斜杠。
    但是在nodejs中,必须要使用RegExp,来构建正则表达式对象。

    router.post('/like_article_search', (req,res) => {
        let searchValue = req.body.value
        console.log(searchValue)
        var str=".*"+searchValue+".*$"
        var reg = new RegExp(str)
    
        Article.find({"title":{$regex:reg,$options: 'i'}}, (err, data) => { // $options:'i' 表示忽略大小写
            if(err) {
                console.log(err)
                return res.status(500).json({
                    result: 1,
                    error_info: err.message
                })
            }
            console.log(data)
            let length = data.length
            return res.status(200).json({
                result: 0,
                count: length,
                searchArticle: data
            })
        })
    })

     

    这样就可以匹配到查询结果。

    2.查询以某个字母开头的集合

    mongodb语法:

    db.UserInfo.find({userName :/^A/})

    nodejs中写法:

    router.post('/like_article_search', (req,res) => {
        let searchValue = req.body.value
        console.log(searchValue)
        var str="^.*"+searchValue+".*$"
        var reg = new RegExp(str)
    
        Article.find({"title":{$regex:reg,$options: 'i'}}, (err, data) => { // {"title": /searchValue/} $options:'i' 表示忽略大小写
            if(err) {
                console.log(err)
                return res.status(500).json({
                    result: 1,
                    error_info: err.message
                })
            }
            console.log(data)
            let length = data.length
            return res.status(200).json({
                result: 0,
                count: length,
                searchArticle: data
            })
        })
    })

    3.多条件模糊查询

    使用$or 语法。

    多字段匹配,title、categroy、lable中包含查询关键词的都进行匹配

    //模糊查询
    router.post('/like_article_search', (req,res) => {
        let searchValue = req.body.value
        // console.log(searchValue)
        // var str=".*"+searchValue+".*$"
        // var reg = new RegExp(str)
        var reg = new RegExp(searchValue);
        var _filter = {
        //多字段匹配
            $or: [
                {'title': {$regex: reg}},
                {'categroy': {$regex: reg}},
                {'lable': {$regex: reg}},
            ]
        }
    
        Article.find(_filter, (err, data) => { // {"title": /searchValue/} $options:'i' 表示忽略大小写
            if(err) {
                console.log(err)
                return res.status(500).json({
                    result: 1,
                    error_info: err.message
                })
            }
            console.log(data)
            let length = data.length
            return res.status(200).json({
                result: 0,
                count: length,
                searchArticle: data
            })
        })
    })

    这样就可以实现。还可以通过某个字段对搜索结果进行降序或升序排列。

     4.全文搜索

    上述正则表达是在效率上等同在该字段上进行全部扫描(除了在该字段上建立索引并使用^符号进行查找,该操作是会走索引的),当需要正则搜索的文档到了一定的量级,模糊是查询的效率还是会很低的。

    全文搜索就是在需要搜索的字段上加上一个文本索引,注意:一个集合只能支持建立一个全文索引,但该索引可以包含多个字段做联合索引。

    Mongo的 $text 和 $search 相关的内容,这是Mongo内置的全文检索,支持多种语言,支持词语权重,在最新的Mongodb 3.2 enterprise版本中,已经增加了对中文文本的搜索。

    数据库结构

     创建索引

    MongoDB提供文本索引以支持对字符串内容的文本搜索查询。text索引可以包括其值为字符串或字符串元素数组的任何字段。 要执行文本搜索查询,必须text在集合上有 索引。集合只能有一个 文本搜索索引,但该索引可以涵盖多个字段。

     

    articleSchema.index({title: 'text', content: 'text', categroy: 'text'})

    查询

    使用$text查询运算符对具有文本索引的集合执行文本搜索。 $text将使用空格和大多数标点符号作为分隔符来标记搜索字符串,并OR在搜索字符串中执行所有此类标记的逻辑

    router.post('/like_article_search', (req,res) => {
        let searchValue = req.body.value
        
        //正则匹配 
        var reg = new RegExp(searchValue);
        
        Article.find({$text:{$search: reg}},{score: {$meta: "textScore"}})
        .sort({score:{$meta: "textScore"}}) 
        .exec((err, data) => { 
            if(err) {
                console.log(err)
                return res.status(500).json({
                    result: 1,
                    error_info: err.message
                })
            }
            console.log(data)
            let length = data.length
            return res.status(200).json({
                result: 0,
                count: length,
                searchArticle: data
            })
        })
    })

    默认情况下,mongodb将以未排序的顺序返回结果。如果要按照相关性得分的顺序进行排序,需要明确的指出对字段进行映射和排序:$meta: textScore

     推荐文章:https://blog.csdn.net/wukongbajieheti/article/details/99715743

    不积跬步无以至千里
  • 相关阅读:
    宋宝华: Linux内核编程广泛使用的前向声明(Forward Declaration)
    朱辉(茶水): Linux Kernel iowait 时间的代码原理
    宋宝华:Linux设备驱动框架里的设计模式之——模板方法(Template Method)
    宋宝华:论程序员的时代焦虑与焦虑的缓解
    邵国际: C 语言对象化设计实例 —— 命令解析器
    让天堂的归天堂,让尘土的归尘土——谈Linux的总线、设备、驱动模型
    宋宝华:关于Ftrace的一个完整案例
    php采集页面指定标签里面的内容
    js调用video的播放时长
    php解析url并得到url中的参数
  • 原文地址:https://www.cnblogs.com/lyt0207/p/13260055.html
Copyright © 2020-2023  润新知