热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

.NET开发过程中的全文索引使用技巧之Solr(转)

前言:相信许多人都听说过.net开发过程中基于Lucene.net实现的全文索引,而Solr是一个高性能,基于Lucene的全文搜索服务器。同时对其进行了扩展,提供了比Lucene

  前言:相信许多人都听说过.net开发过程中基于Lucene.net实现的全文索引,而Solr是一个高性能,基于Lucene的全文搜索服务器。同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能进行了优化,并且提供了一个完善的功能管理界面,是一款非常优秀的全文搜索引引擎,这里我就绕过Lucene,直接说Solr的应用了,总之,Solr比Lucene更加方便简洁好用,而且上手快,开发效率高。

   Solr应用场景:涉及到大数据的全文搜索。尤其是电子商务平台还有现在流行的云计算,物联网等都是需要强大的数据量作为支撑的,使用Solr来进行数据 检索最合适不过了,而且Solr是免费开源的,门槛低、投资少见效快。关于Solr的一些优点我这里就不在累赘陈述了,园子里也有很多大神也写了很多关于 Solr的技术博文,我这里也只是抛砖引玉,见笑了。

   好了,这里就开始Solr的奇幻之旅吧

基于.NET平台下的Solr开发步骤

一、搭建Solr服务器,具体步骤如下:

   1.安装JDK,因为是.NET平台,不需要安装JRE、JAVA虚拟机,只安装JDK即可,而且安装JDK不需要手动去配置环境变量,它会自动帮我们配置好环境变量,很方便,这里我安装的是jdk1.7,官网地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html

   2.安装Tomcat8.0,官网地址:http://tomcat.apache.org/download-80.cgi,安装完成后启动Monitor Tomcat,浏览器地址栏输入http://localhost:8080/,能进入说明安装成功

   3.下载Solr,这里我用的是Solr4.4版本,下载后进行下列配置

  (1)解压Solr4.4,创建Solr目录,比如D:/SorlServer/one,将解压后的Solr4.4中的example目录下的Solr文件夹中的所有文件拷贝到创建的目录中

  (2)创建Solr Web应用,具体步骤,将解压后的Solr4.4中的dist目录下的Solr-4.4.0.war文件拷贝到Tomcat下,比如C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps下,重命名为one.war,启动Tomcat后该文件会自动解压,进入到D:\SorlServer\one\collection1\conf下,打开solrconfig.xml文件,找到 节点改为${solr.data.dir:c:/SorlServer/one/data}

注意:这一步很重要:打开C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\One\WEB-INF下的web.xml文件,找到节点开启,

将env-entry-value值改为D:/SorlServer/one,如下:

      

      solr/home

      D:/SorlServer/one

      java.lang.String

   (3)将解压后的Solr4.4下的/dist/solrj-lib目录中的所有jar包拷贝到C:\Program Files\Apache Software Foundation\Tomcat 7.0\lib中

  (4)停止Tomcat,然后再启动,访问http://localhost:8080/one,即可打开

注意:如果是开发英文网站,我们就不需要使用第三方的分词配置,Solr本身就内置支持英文分词,如果是其他语种比如小语种(日语、意大利、法语等等),大家可以去网上找相关的分词包,这里我们以中文分词为例,毕竟国内大部分网站都是中文为主的。

   4.配置中文分词,国内常用的分词器(庖丁解牛、mmseg4j、IKAnalyzer),这里我用的是IKAnalyzer,这个分词器比较活跃而且更新也快,挺好用的,具体步骤如下:

   (1)将IKAnalyzer的jar包以及IKAnalyzer.cfg.xml都复制到C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\one\WEB-INF\lib下

   (2)配置D:\SorlServer\one\collection1\conf下的schema.xml,添加如下配置:

     

    

    (3)停止Tomcat,然后再启动,访问http://localhost:8080/one/#/collection1/analysis,即可进行测试

    以上是Solr服务器端的相关配置工作

二、开始基于.NET平台的Solr开发:

   1.下载Solr客户端组件,我用的是园子里的Terry大哥的EasyNet.Solr,地址在微软开源站:http://easynet.codeplex.com/,

Terry大哥已经把solr客户端封装的很完善了,里面封装了很多现成的方法和参数配置,我们直接可以拿过来用,利用Easynet.solr创建索引,然后再查询索引,具体使用方法如下:

  (1)下载EasyNet.Solr源码直接放到项目中,也可以将源码生成Dll组件后添加到项目引用进行使用,把源码放到项目中最好不过了,我们也可以对其进行调整来满足自己的需要

  (2)创建索引实体类,就是我们要保存的索引数据,比如创建一个产品实体类 

 

技术分享图片
using System;
using System.Collections.Generic;

namespace Seek.SearchIndex
{
    public partial class IndexProductModel
    {
        public IndexProductModel()
        {
        }

        #region  Properties
        public int ID { get; set; }
        public int ProductID { get; set; }
        public string ClassPath { get; set; }
        public int ClassID1 { get; set; }
        public int ClassID2 { get; set; }
        public int ClassID3 { get; set; }
        public string Title { get; set; }
        public string Model { get; set; }
        public string PriceRange { get; set; }
        public string AttributeValues { get; set; }
        public string ProductImages { get; set; }
        public int MemberID { get; set; }
        public System.DateTime CreateDate { get; set; }
        public System.DateTime LastEditDate { get; set; }
        public string FileName { get; set; }
        public string ProductType { get; set; }
        public string Summary { get; set; }
        public string Details { get; set; }
        public string RelatedKeywords { get; set; }
        public int MemberGrade { get; set; }
        #endregion
    }
}
技术分享图片

     (3)配置Solr服务器端的xml,就是将咱们的这个索引实体类配置到Solr服务器上,进入D:\SorlServer\one\collection1\conf,打开schema.xml文件,配置如下

  

技术分享图片
"ID" type="string" indexed="true" stored="true" required="true" multiValued="false" /> 
   "ProductID" type="int" indexed="true" stored="true"/>
   
   "Title" type="text_en_splitting" indexed="true" stored="true" termVectors="true" termPositiOns="true"  termOffsets="true"/>
   "Model" type="text_en_splitting" indexed="true" stored="true" termVectors="true" termPositiOns="true"  termOffsets="true"/>
   "ClassPath" type="string" indexed="true" stored="true"/>
   "ClassID1" type="int" indexed="true" stored="true"/>
   "ClassID2" type="int" indexed="true" stored="true"/>
   "ClassID3" type="int" indexed="true" stored="true"/>
   "PriceRange" type="string" indexed="true" stored="true"/>
   "AttributeValues" type="string" indexed="true" stored="true"/>
   "ProductImages" type="string" indexed="true" stored="true"/>
   "MemberID" type="int" indexed="true" stored="true"/>
   "CreateDate" type="date" indexed="true" stored="true"/>
   "LastEditDate" type="date" indexed="true" stored="true"/>
   "FileName" type="string" indexed="true" stored="true"/>
   "ProductType" type="string" indexed="true" stored="true"/>
   "Summary" type="string" indexed="true" stored="false"/>
   "Details" type="string" indexed="true" stored="false"/>
   "RelatedKeywords" type="string" indexed="true" stored="true"/>
   "MemberType" type="string" indexed="true" stored="true"/>
   "MemberGrade" type="int" indexed="true" stored="true"/>
技术分享图片

    (4)开始创建索引,最好能写一个生成索引的客户端程序,我这里提供一下自己的索引器关键代码

  

技术分享图片
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Seek.SearchIndex;
using System.Data;
using System.Threading;
using System.Configuration;
using System.Reflection;
using EasyNet.Solr;
using EasyNet.Solr.Impl;
using EasyNet.Solr.Commons;
using System.Xml.Linq;
using EasyNet.Solr.Commons.Params;
using System.Threading.Tasks;

namespace Seek.SearchIndex
{
    /// 
    /// 索引器
    /// 
    public class Indexer
    {
        private readonly static OptimizeOptions optimizeOptiOns= new OptimizeOptions();
        private readonly static CommitOptions commitOptiOns= new CommitOptions() { SoftCommit = true };
        private readonly static ISolrResponseParser binaryRespOnseHeaderParser= new BinaryResponseHeaderParser();
        private readonly static IUpdateParametersConvert updateParametersCOnvert= new BinaryUpdateParametersConvert();
        private readonly static ISolrQueryConnection cOnnection= new SolrQueryConnection() { ServerUrl = ConfigurationManager.AppSettings["SolrServer"] };
        private readonly static ISolrUpdateConnection solrUpdateCOnnection= new SolrUpdateConnection() { ServerUrl = ConfigurationManager.AppSettings["SolrServer"], COntentType= "application/javabin" };
        private readonly static ISolrUpdateOperations solr = new SolrUpdateOperations(solrUpdateConnection, updateParametersConvert) { RespOnseWriter= "javabin" };
        private readonly static ISolrQueryOperations solrQuery = new SolrQueryOperations(connection) { RespOnseWriter= "javabin" };

        public enum State
        {
            /// 
            /// 运行中
            /// 
            Runing,
            /// 
            /// 停止
            /// 
            Stop,
            /// 
            /// 中断
            /// 
            Break
        }
        /// 
        /// 窗口
        /// 
        private Main form;
        /// 
        /// 线程
        /// 
        public Thread t;
        /// 
        /// 消息状态
        /// 
        public State state = State.Stop;
        /// 
        /// 当前索引
        /// 
        private long currentIndex = 0;

        public long CurrentIndex
        {
            get { return currentIndex; }
            set { currentIndex = value; }
        }

        private int _startId = AppCongfig.StartId;

        public int StartId
        {
            get { return _startId; }
            set { _startId = value; }
        }

        /// 
        /// 产品总数
        /// 
        private int productsCount = 0;
        /// 
        /// 起始时间
        /// 
        private DateTime startTime = DateTime.Now;
        /// 
        /// 结束时间
        /// 
        private DateTime endTime = DateTime.MinValue;
        private static object syncLock = new object();
        #region 单利模式
        private static Indexer instance = null;

        private Indexer(Main _form)
        {
            form = _form;
            productsCount = DataAccess.GetCount(0);       //产品数统计
            form.fullerTsslMaxNum.Text = productsCount.ToString();
            form.fullerProgressBar.Minimum = 0;
            form.fullerProgressBar.Maximum = productsCount;
        }
        public static Indexer GetInstance(Main form)
        {
            if (instance == null)
            {
                lock (syncLock)
                {
                    if (instance == null)
                    {
                        instance = new Indexer(form);
                    }
                }
            }
            return instance;
        }
        #endregion

        /// 
        /// 启动
        /// 
        public void Start()
        {
            ThreadStart ts = new ThreadStart(FullerRun);
            t = new Thread(ts);
            t.Start();
        }
        /// 
        /// 停止
        /// 
        public void Stop()
        {
            state = State.Stop;
        }
        /// 
        /// 中断
        /// 
        public void Break()
        {
            state = State.Break;
        }


        /// 
        /// 创建索引
        /// 
        public void InitIndex(object data)
        {
            var docs = new List();
            DataTable list = data as DataTable;
            foreach (DataRow pro in list.Rows)
            {
                var model = new SolrInputDocument();

                PropertyInfo[] properites = typeof(IndexProductModel).GetProperties();//得到实体类属性的集合
                string[] dateFields = { "CreateDate", "LastEditDate" };
                string field = string.Empty;//存储fieldname
                foreach (PropertyInfo propertyInfo in properites)//遍历数组
                {
                    object val = pro[propertyInfo.Name];
                    if (val != DBNull.Value)
                    {
                        model.Add(propertyInfo.Name, new SolrInputField(propertyInfo.Name, val));
                    }
                }
                docs.Add(model);

                StartId = Convert.ToInt32(pro["ID"]);
            }
            GetStartId();
            lock (syncLock)
            {
                if (currentIndex <= productsCount)
                {
                    form.fullerProgressBar.Value = (int)currentIndex;
                }
                form.fullerTsslCurrentNum.Text = currentIndex.ToString();
            }
            var result = solr.Update("/update", new UpdateOptions() {  Docs = docs });
        }

        /// 
        /// 创建索引
        /// 
        public void CreateIndexer(DataTable dt)
        {
            GetStartId();
            Parallel.ForEach(dt.AsEnumerable(), (row) =>
            {
                //从数据库查询商品详细属性
                if (row != null)
                {
                    var docs = new List();
                    var model = new SolrInputDocument();

                    PropertyInfo[] properites = typeof(IndexProductModel).GetProperties();//得到实体类属性的集合
                    string[] dateFields = { "CreateDate", "LastEditDate" };
                    string field = string.Empty;//存储fieldname
                    foreach (PropertyInfo propertyInfo in properites)//遍历数组
                    {
                        object val = row[propertyInfo.Name];
                        if (val != DBNull.Value)
                        {
                            model.Add(propertyInfo.Name, new SolrInputField(propertyInfo.Name, val));
                        }
                    }
                    docs.Add(model);

                    StartId = Convert.ToInt32(row["ID"]);
                    var result = solr.Update("/update", new UpdateOptions() { Docs = docs });
                }
            });

            //GetStartId();
            lock (syncLock)
            {
                if (currentIndex <= productsCount)
                {
                    form.fullerProgressBar.Value = (int)currentIndex;
                }
                form.fullerTsslCurrentNum.Text = currentIndex.ToString();
            }
        }

        /// 
        /// 全部索引运行
        /// 
        public void FullerRun()
        {
            //GetStartId();
            //form.fullerTsslCurrentNum.Text = currentIndex.ToString();
            DataTable dt = DataAccess.GetNextProductsInfo(StartId);
            StartId = AppCongfig.StartId;
            if (state == State.Break)
            {
                this.SendMesasge("完全索引已继续,起始ID[" + StartId + "]...");
            }
            else
            {
                startTime = DateTime.Now;
                this.SendMesasge("完全索引已启动,起始ID[" + StartId + "]...");
            }
            state = State.Runing;
            form.btnInitIndex.Enabled = false;
            form.btnSuspend.Enabled = true;
            form.btnStop.Enabled = true;
      
            while (dt != null && dt.Rows.Count > 0 && state == State.Runing)
            {
                try
                {
                    InitIndex(dt);//单线程
                   // CreateIndexer(dt);//多线程
                }
                catch (Exception ex)
                {
                    state = State.Stop;
                    form.btnInitIndex.Enabled = true;
                    form.btnSuspend.Enabled = false;
                    form.btnStop.Enabled = false;
                    GetStartId();
                    this.SendMesasge(ex.Message.ToString());
                }
                form.fullerTsslTimeSpan.Text = "已运行 :" + GetTimeSpanShow(DateTime.Now - startTime) + ",预计还需:" + GetTimeSpanForecast();

                try
                {
                    dt = DataAccess.GetNextProductsInfo(StartId);//获取下一组产品
                }
                catch (Exception err)
                {
                    this.SendMesasge("获取下一组产品出错,起始ID[" + StartId + "]:" + err.Message);
                }
            }
            if (state == State.Runing)
            {
                state = State.Stop;
                form.btnInitIndex.Enabled = true;
                form.btnSuspend.Enabled = false;
                form.btnStop.Enabled = false;
                AppCongfig.SetValue("StartId", StartId.ToString());
                this.SendMesasge("完全索引已完成,总计索引数[" + currentIndex + "]结束的产品Id" + StartId);
            }
            else if (state == State.Break)
            {
                GetStartId();
                state = State.Break;
                form.btnInitIndex.Enabled = true;
                form.btnSuspend.Enabled = false;
                form.btnStop.Enabled = false;
                AppCongfig.SetValue("StartId", StartId.ToString());
                this.SendMesasge("完全索引已暂停,当前索引位置[" + currentIndex + "]结束的产品Id" + StartId);
            }
            else if (state == State.Stop)
            {
                GetStartId();
                state = State.Stop;
                this.SendMesasge("完全索引已停止,已索引数[" + currentIndex + "]结束的产品Id" + StartId);
                form.btnInitIndex.Enabled = true;
                form.btnSuspend.Enabled = false;
                form.btnStop.Enabled = false;
                AppCongfig.SetValue("StartId", StartId.ToString());
                productsCount = DataAccess.GetCount(StartId);       //产品数统计
                form.fullerTsslMaxNum.Text = productsCount.ToString();
                form.fullerProgressBar.Minimum = 0;
                form.fullerProgressBar.Maximum = productsCount;
            }
            endTime = DateTime.Now;
        }

        /// 
        /// 多线程构建索引数据方法
        /// 
        /// 
        public void MultiThreadCreateIndex(object threadDataParam)
        {
            InitIndex(threadDataParam);
        }

        /// 
        /// 获取最大的索引id
        /// 
        private void GetStartId()
        {
            IDictionary<string, ICollection<string>> optiOns= new Dictionary<string, ICollection<string>>();
            options[CommonParams.SORT] = new string[] { "ProductID DESC" };
            options[CommonParams.START] = new string[] { "0" };
            options[CommonParams.ROWS] = new string[] { "1" };
            options[HighlightParams.FIELDS] = new string[] { "ProductID" };
            options[CommonParams.Q] = new string[] { "*:*" };
            var result = solrQuery.Query("/select", null, options);
            var solrDocumentList = (SolrDocumentList)result.Get("response");
            currentIndex = solrDocumentList.NumFound;
            if (solrDocumentList != null && solrDocumentList.Count() > 0)
            {
                StartId = (int)solrDocumentList[0]["ProductID"];
                //AppCongfig.SetValue("StartId", solrDocumentList[0]["ProductID"].ToString());
            }
            else
            {
                StartId = 0;
                // AppCongfig.SetValue("StartId", "0");
            }
        }


        /// 
        /// 优化索引
        /// 
        public void Optimize()
        {
            this.SendMesasge("开始优化索引,请耐心等待...");
            var result = solr.Update("/update", new UpdateOptions() { OptimizeOptiOns= optimizeOptions });
            var header = binaryResponseHeaderParser.Parse(result);
            this.SendMesasge("优化索引耗时:" + header.QTime + "毫秒");
        }

        /// 
        /// 发送消息到界面
        /// 
        /// 发送消息到界面
        protected void SendMesasge(string message)
        {
            form.fullerDgvMessage.Rows.Add(form.fullerDgvMessage.Rows.Count + 1, message, DateTime.Now.ToString());
        }
        /// 
        /// 获取时间间隔显示
        /// 
        /// 时间间隔
        /// 
        protected string GetTimeSpanShow(TimeSpan ts)
        {
            string text = "";
            if (ts.Days > 0)
            {
                text += ts.Days + "";
            }
            if (ts.Hours > 0)
            {
                text += ts.Hours + "";
            }
            if (ts.Minutes > 0)
            {
                text += ts.Minutes + "";
            }
            if (ts.Seconds > 0)
            {
                text += ts.Seconds + "";
            }
            return text;
        }
        /// 
        /// 获取预测时间
        /// 
        /// 
        protected string GetTimeSpanForecast()
        {
            if (currentIndex != 0)
            {
                TimeSpan tsed = DateTime.Now - startTime;
                double d = ((tsed.TotalMilliseconds / currentIndex) * productsCount) - tsed.TotalMilliseconds;
                return GetTimeSpanShow(TimeSpan.FromMilliseconds(d));
            }
            return "";
        }
    }
}
技术分享图片

    (5)运行索引器,创建索引,这里是我的索引器界面,如图

技术分享图片

  可以随时跟踪索引生成的情况

  (6)索引创建完毕后,可以进入Solr服务器界面http://localhost:8080/one/#/collection1/query进行测试

 

以上就是Solr的前期工作,主要是Solr服务器搭建和客户端调用生成索引,后期再对客户端的查询进行详细的说明,下期预告

1.全文搜索,分词配置,以及类似于谷歌和百度那种输入关键字自动完成功能

2.Facet查询

.NET开发过程中的全文索引使用技巧之Solr(转)


推荐阅读
  • 本指南详细介绍了如何在CentOS 6.6 64位系统上以root用户身份部署Tomcat 8服务器。系统环境为CentOS 6.6 64位,采用源码安装方式。所需软件为apache-tomcat-8.0.23.tar.gz,建议将软件下载至/root/opt目录。具体下载地址请参见官方资源。本指南涵盖了从环境准备到服务启动的完整步骤,适用于需要在该系统环境下搭建高性能Web应用服务器的技术人员。 ... [详细]
  • 一:什么是solrSolr是apache下的一个开源项目,使用Java基于lucene开发的全文搜索服务器;Lucene是一个开放源代 ... [详细]
  • Nexus3.0.0+Maven的使用(一)
    1、Nexus介绍Nexus是一个强大的Maven仓库管理器,它极大地简化了自己内部仓库的维护和外部仓库的访问。利用Nexus你可以只在一个地方就能够完全控制访问和部署在你所维护仓 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 本文深入探讨了Java多线程环境下的同步机制及其应用,重点介绍了`synchronized`关键字的使用方法和原理。`synchronized`关键字主要用于确保多个线程在访问共享资源时的互斥性和原子性。通过具体示例,如在一个类中使用`synchronized`修饰方法,展示了如何实现线程安全的代码块。此外,文章还讨论了`ReentrantLock`等其他同步工具的优缺点,并提供了实际应用场景中的最佳实践。 ... [详细]
  • camel_使用Camel在来自不同来源的Solr中索引数据
    camelApacheSolr是建立在Lucene之上的“流行的,快速的开源企业搜索平台”。为了进行搜索(并查找结果),通常需要从不同的源(例如内容管理 ... [详细]
  • Lucene 全文检索技术入门
    一、搜索引擎的历史萌芽:Archie、Gopher起步:Robot(网络机器人)的出现与spider(网络爬虫)发展:excite、galax ... [详细]
  • 说明:搜索模块针对的是买家用户,在找菜品找的很费劲下的一种查询方面。目前也是快速的检索商品。对于移动端的APP买家用户而言,要求的速度在3秒内完成。支持模糊查询,由于业务实战表面, ... [详细]
  • 在 Android 开发中,`android:exported` 属性用于控制组件(如 Activity、Service、BroadcastReceiver 和 ContentProvider)是否可以被其他应用组件访问或与其交互。若将此属性设为 `true`,则允许外部应用调用或与之交互;反之,若设为 `false`,则仅限于同一应用内的组件进行访问。这一属性对于确保应用的安全性和隐私保护至关重要。 ... [详细]
  • 在Eclipse中提升开发效率,推荐使用Google V8插件以增强Node.js的调试体验。安装方法有两种:一是通过Eclipse Marketplace搜索并安装;二是通过“Help”菜单中的“Install New Software”,在名称栏输入“googleV8”。此插件能够显著改善调试过程中的性能和响应速度,提高开发者的生产力。 ... [详细]
  • 深入解析Java虚拟机的内存分区与管理机制
    Java虚拟机的内存分区与管理机制复杂且精细。其中,某些内存区域在虚拟机启动时即创建并持续存在,而另一些则随用户线程的生命周期动态创建和销毁。例如,每个线程都拥有一个独立的程序计数器,确保线程切换后能够准确恢复到之前的执行位置。这种设计不仅提高了多线程环境下的执行效率,还增强了系统的稳定性和可靠性。 ... [详细]
  • Python 伦理黑客技术:深入探讨后门攻击(第三部分)
    在《Python 伦理黑客技术:深入探讨后门攻击(第三部分)》中,作者详细分析了后门攻击中的Socket问题。由于TCP协议基于流,难以确定消息批次的结束点,这给后门攻击的实现带来了挑战。为了解决这一问题,文章提出了一系列有效的技术方案,包括使用特定的分隔符和长度前缀,以确保数据包的准确传输和解析。这些方法不仅提高了攻击的隐蔽性和可靠性,还为安全研究人员提供了宝贵的参考。 ... [详细]
  • 该问题可能由守护进程配置不当引起,例如未识别的JVM选项或内存分配不足。建议检查并调整JVM参数,确保为对象堆预留足够的内存空间(至少1572864KB)。此外,还可以优化应用程序的内存使用,减少不必要的内存消耗。 ... [详细]
  • 2018深入java目标计划及学习内容
    本文介绍了作者在2018年的深入java目标计划,包括学习计划和工作中要用到的内容。作者计划学习的内容包括kafka、zookeeper、hbase、hdoop、spark、elasticsearch、solr、spring cloud、mysql、mybatis等。其中,作者对jvm的学习有一定了解,并计划通读《jvm》一书。此外,作者还提到了《HotSpot实战》和《高性能MySQL》等书籍。 ... [详细]
  • 部署solr建立nutch索引
    2019独角兽企业重金招聘Python工程师标准接着上篇nutch1.4的部署应用,我们来部署一下solr,solr是对lucene进行了封装的企 ... [详细]
author-avatar
克湖泓瑜24
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有