zoukankan      html  css  js  c++  java
  • ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(七) 之 历史记录查询(时间,关键字,图片,文件),关键字高亮显示。

    前言

      上一篇讲解了如何自定义右键菜单,都是前端的内容,本篇内容就一个:查询。聊天历史纪录查询,在之前介绍查找好友的那篇博客里已经提到过 Elasticsearch,今天它又要上场了。对于Elasticsearch不感冒的同学呢,本篇可以不用看啦。

      from baidu:

      ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。
    我们建立一个网站或应用程序,并要添加搜索功能,令我们受打击的是:搜索工作是很难的。我们希望我们的搜索解决方案要快,我们希望有一个零配置和一个完全免费的搜索模式,我们希望能够简单地使用JSON通过HTTP的索引数据,我们希望我们的搜索服务器始终可用,我们希望能够一台开始并扩展到数百,我们要实时搜索,我们要简单的多租户,我们希望建立一个云的解决方案。Elasticsearch旨在解决所有这些问题和更多的问题。

    DEMO演示

      随便聊聊天:

        

      图片类型过滤

      

      文件类型过滤

      

      关键字查询

      

      时间段查询(截图略)

    实战讲解

      layim 已经给我们提供了打开历史纪录页面的接口。不过查询历史纪录页面需要自己布局。由于html+css不是我的强项,我就直接把聊天室的结构拿过去了。聊天历史纪录页面上就一个ajax请求,还有数据绑定,这些都不多做介绍。主要是讲一下后台如何进行数据查询和细节注意事项。主要还是讲到了Elasticsearch,对于Elasticsearch不感兴趣的小伙伴可以略过本篇。

      首先呢,想要查询历史纪录,要先保存数据。那么在之前的LayIMHub中的接受消息方法中,我们已经把数据顺便在ES中存储一份。(实例代码如下)

      

     //保存消息
                Task.Run(() => {
                    MessageFactory.CreateInstance(ChatMessageSaveType.SearchEngine).Send(message);
                });
                ChatInfo chatInfo;
                var mine = message.mine;
    //聊天记录model chatInfo
    = new ChatInfo { addtime = message.addtime, avatar = mine.avatar, content = mine.content, nickname = mine.username, qq = mine.id, timespan = message.addtime.ToTimestamp(), roomid = message.roomid, isfile = mine.content.IndexOf("file(") > -1, isimg = mine.content.IndexOf("img[") > -1 };
    //在es中,index是索引的意思,相当于数据库中的表
    bool result= es.Index(chatInfo); return new SendMessageResult(result);

      于是,我们用户聊天的时候,将数据就保存到了ES当中,正如SQL Server做搜索一样,想用ES搜索,它也需要保存一份。我们打开客户端看一下数据,如果你也安装了ES和head插件,那么浏览器输入 127.0.0.1:9200/_plugin/head就可以看数据了。

      

      那么数据已经有了,我们看一下查询条件。 1,关键字查询 2,类型查询 3,时间段查询 4,聊天室id查询(最基本,A和B聊天不能查询A和C的历史纪录)

      他们之间的查询关系是and条件,如果用sql表示的话就是   select * from chathistory where roomid=1 and content like '%诛仙%' and 。。。

      那么我们就需要把SQL翻译成ES的语法。最终结果是这样的。

      

    {
      "query": {
        "filtered": {
          "filter": {
            "and": [  //and关系
              {
                "query": {
                  "match": {
                    "roomid": "FRIEND_14895_14894"  //根据聊天室id过滤
                  }
                }
              },
              {
                "term": {
                  "isimg": false     //是否是img
                }
              },
              {
                "range": {  //range查询
                  "addtime": {   //查询字段是时间类型
                    "gt": "2016-08-16T00:00:00"    //gt 是大于某个时间 lt 是小于某个时间
                  }
                }
              }
            ]
          }
        }
      },
      "from": 0, //分页
      "size": 50,
      "sort": { //排序
        "addtime": {
          "order": "asc"
        }
      },
      "highlight": { //高亮
        "fields": {
          "content": {} //content高亮显示
        }
      }
    }

      核心查询方法如下:(.NET客户端用的PlainElastic.Net,他已经对构造查询语句做了封装,类似ORM,但是语法我用的太蹩脚了,于是只有自己拼“SQL”了)

      public JsonResultModel SearchHistoryMsg(string groupId, DateTime? starttime = null, DateTime? endtime = null, string keyword = null, bool isfile = false, bool isimg = false, int pageIndex = 1, int pageSize = 20)
            {
                string st = starttime == null ? "" : starttime.Value.ToString("yyyy-MM-dd");
                string et = endtime == null ? "" : endtime.Value.ToString("yyyy-MM-dd");
                int from = (pageIndex - 1) * pageSize;
                //某个聊天组查询
                string queryGroup = "{"query": {"match": { "roomid": "FRIEND_14895_14894" }}}";
                //关键字查询
                string queryKeyWord = "{ "query": {"match_phrase": {"content": {"query": "" + keyword + "","slop": 0} } }}";
                //是否图片 查询
                string queryImg = "{ "term": {"isimg": true }}";
                //是否包含文件查询
                string queryFile = "{ "term": {"isfile": true }}";
                //大于小于某个时间段查询
                string queryTimeRange = "{"range": {"addtime": { "gt": ""+st+"","lt": ""+et+"" }} }";
                //大于某个时间
                string queryTimeRangeGt = "{"range": {"addtime": { "gt": ""+st+""}} }";
                //小于某个时间
                string queryTimeRangeLt = "{"range": {"addtime": { "lt": "" + et + "" }} }";
                string queryAnd = queryGroup;
                if (starttime != null&&endtime!=null) {
                    queryAnd += "," + queryTimeRange;
                }
                if (starttime != null) {
                    queryAnd += "," + queryTimeRangeGt;
                }
                if (endtime != null) {
                    queryAnd += "," + queryTimeRangeLt;
                }
                if (!string.IsNullOrEmpty(keyword)) {
                    queryAnd += "," + queryKeyWord;
                }
                if (isfile) {
                    queryAnd += "," + queryFile;
                }
                if (isimg) {
                    queryAnd += "," + queryImg;
                }
                //最终查询语句
                string query = "  {"query": {"filtered": {"filter": {"and": [" + queryAnd + "] }}},"from": " + from + ","size": " + pageSize + ","sort": {"addtime": { "order": "asc"}},"highlight": {"fields": { "content": {}} }}";
    
    
                var result = eschat.QueryBayConditions(query);
                return JsonResultHelper.CreateJson(result, true);
            }

      那么,只要条件给对了,结果自然就是我们想要的结果了。

      不过,搜索也是会出现bug的,例如,如果输入关键字img或者file,就会出现下面这种情况,因为数据库里存的就是那一串html,然后到界面上又做了相应的处理,这个情况就有点蛋疼了。

      

         有同学会注意到 img旁边有em标签,其实这个就是关键字高亮的原因所在。好比,上边的演示中,诛仙两个字是高亮的,查看源代码,他们每个字都会有em标签包含,那是因为ES在查询过程中,你可以使用高亮功能,他会把符合条件的关键字给你加上特殊标签,当然我们也可以自定义标签,例如 b,i ,tag  都可以。然后给一个样式,比如我这里 em {color:red} 那么高亮功能就出来了。

    总结

      本篇呢基本上都是围绕Elasticsearch来讲,由于属于一些额外的功能,所以也没讲太细。搜索功能用SQL或者MySQL或者其他的一些数据库都能实现,主要是对接layim要注意,绑定的方式以及图片文件的html转换等。

          下篇预告【中级】ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(八) 之 聊天室的小细节,你都注意到了吗?

       

       想要学习的小伙伴,可以关注我的博客哦,我的QQ:645857874,Email:fanpan26@126.com

      GitHub:https://github.com/fanpan26/LayIM_NetClient/

  • 相关阅读:
    利用border-radius画椭圆
    关于使用svg构建六边形蜂巢列表的方式
    JavaScript拖拽效果的原理及实现
    逆战班-JS的形参与实参
    前端面试&笔试汇总
    less学习---less的混合(mixin)
    less学习---less的嵌套规则
    less学习----less变量
    vue-cli3实现将数据导出为Excel表
    js中apply和call方法浅析
  • 原文地址:https://www.cnblogs.com/panzi/p/5778330.html
Copyright © 2011-2022 走看看