react初始配置

下面webpack babel react 2018年最新最小化配置模板 package.js { "name": "{{NAME}}", "version": "1.0.0", "description": "{{DESCRIPTION}}", "main": "index.js", "scripts": { "start": "webpack-dev-server", "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", "url": "" }, "author": "", "license": "LexisNexis", "devDependencies": { "babel-core": "^6.26.0", "babel-loader": "^7.1.2", "babel-preset-env": "^1.6.1", "babel-preset-react": "^6.24.1", "html-webpack-plugin": "^2.30.1", "path": "^0.12.7", "webpack": "^3.11.0", "webpack-dev-server": "^2.11.1" }, "dependencies": { "react": "^16.2.0", "react-dom": "^16.2.0" } } webpack.config.js const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({ template: './client/index.html', filename: 'index.html', inject: 'body' }); module.exports = { entry: './client/index.jsx', output: { path: path.resolve('dist'), filename: 'app.js' }, module: { loaders: [ { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ }, { test: /\.jsx$/, loader: 'babel-loader', exclude: /node_modules/ } ] }, plugins: [HtmlWebpackPluginConfig] }; .babelrc ...

February 13, 2018

solr7配置同义词

Solr的同义词可以满足绝大部分的需求,可以配置双向,也可以配置单向的同义词列表,功能非常的强大。 Solr的同义词可以在两个方面设置,一是索引的时候;二是查询的时候;或者你同时设置两者,同时设置的时候会非常复杂,会产生意想不到的结果。 先从基本配置开始 假设我们有同义词列表synonyms_en.txt ability,capability 配置Solr的fieldtype <fieldType name="text_en" class="solr.TextField" positionIncrementGap="100"> <analyzer type="index"> <tokenizer class="solr.StandardTokenizerFactory"/> <!-- synonym --> <filter class="solr.SynonymGraphFilterFactory" synonyms="synonyms_en.txt" ignoreCase="true" expand="false"/> ...... </analyzer> <analyzer type="query"> ...... </analyzer> </fieldType> 先尝试索引时候设置同义词,直接在analyzer type="index"内部配置即可,SynonymGraphFilterFactory暂时还是一个试验性质的功能,以后的版本可能会有所改动。class还可以设置成solr.SynonymFilterFactory Solr自带的同义词配置有很多的参数: synonyms:指定同义词列表文件 ignoreCase:顾名思义是忽略大小写 expand:是否扩展同义词,意思是a和b是同义词,如果设置为true,那么搜索a的时候,同时搜索a和b,如果设置为false,那么搜索a的时候就搜索a,搜索b的时候也搜索a。也就是说单向双向的概念:如果设置为true,那么就是双向的;如果设置为false就是单向的,后面的词会转换成前面的词搜索。 tokenizerFactory:指定同义词列表使用的分词器 dedup:是否忽略重复,true为忽略 根据上面的设置,如果搜索ability,那么最终搜索的也是ability。如果搜索的是capability,最终搜索的时候会把capability转换成ability搜索。这样就达到了同义词搜索的功能。 查询时使用同义词 只需要把index部分的配置移到query部分即可,如下: <fieldType name="text_en" class="solr.TextField" positionIncrementGap="100"> <analyzer type="index"> ...... </analyzer> <analyzer type="query"> <tokenizer class="solr.StandardTokenizerFactory"/> <!-- synonym --> <filter class="solr.SynonymGraphFilterFactory" synonyms="synonyms_en.txt" ignoreCase="true" expand="false"/> ...... </analyzer> </fieldType> 如果这时候把expand设置成true,那么搜索任何一个词,最终都会转换成搜索:SynonymQuery(Synonym(field:ability field:capability))。注意你看到的可能会是SynonymQuery(Synonym(title.en:abil title.en:capabl)),这是使用了porter stemming之后的结果。 我的请求语句如下: http://192.168.0.106:8983/solr/lnc/select?debug=query&df=title.en&q=capability 单向,双向概念 这两个概念弄得还是有点模糊。第一:如果设置expand=false,那么同义词都会转换成第一个词进行索引(或者查询);第二:如果设置expand=true,那么一个词会扩展成多个词同时查询;第三:使用ability => capability的配置时,如果查询ability,不管expand是true还是false,都会转换成对capability的搜索。 我理解的单向可以做成下面的列表: ...

January 10, 2018

Solr7从搭建到入坑

solr7搭建运行非常简单,首先下载压缩包,然后解压,到解压出来的目录执行:bin/solr start即可启动solr。以这种方式启动的solr是single core的模式。推荐部署cloud模式,可以有更好的伸缩性与扩展性,使用:bin/solr start -c可以启动cloud模式。下面主要针对cloud模式介绍solr7.2.1的搭建与查询。 solr7自带了几个例子,可以从例子可以深入solr。 以SolrCloud模式启动Solr 要启动solr,在Linux或者Unix执行:bin/solr start -e cloud,windows下执行:bin\solr.cmd start -e cloud,默认启动2个node组成的cloud server。这将会进入一个交互模式的启动过程,如果想跳过交互模式,启动命令添加参数-noprompt。如果是交互模式,一路回车到下面的提示: Now let's create a new collection for indexing documents in your 2-node cluster. Please provide a name for your new collection: [gettingstarted] 输入techproducts回车,我们创建的collection名字是techproducts。 继续回车到选择配置的地方: Please choose a configuration for the techproducts collection, available options are: _default or sample_techproducts_configs [_default] 这里有一个configSet的概念,configSet相当于是一个所有配置文件存放的地方,所有创建的collection都要在这里读取配置文件。 _default是一个基本的配置集,还有一个包含了techproducts的配置集,这个配置集可以用来支持我们想使用的techproducts样例数据。 输入sample_techproducts_configs回车。 恭喜,Solr已经启动好了!通过在浏览器访问http://localhost:8983/solr,这将是入坑的起点。 通过上面的步骤,创建了了两个节点(2 nodes),一个运行在7574端口,另外一个运行在8983端口,一个collection techproducts,两个shard(分片),每个分片又有两个拷贝,这样的配置可以在某个分片出现问题的时候快速恢复。 |-- 127.0.1.1:7574 |-- shard1 --|-- 127.0.0.1:8983 techproducts --| |-- shard2 --|-- 127.0.1.1:7574 |-- 127.0.0.1:8983 索引techproducts样例数据 上面已经启动了solr,但是里面还没有数据,现在还不能做查询。 ...

October 8, 2017

自定义Lucene的分词器Analyzer

0、先定义一下分词的结果 从最简单的做起,把输入的内容按一个字一个字进行切分。这里只是为了说明自定义的Analyzer以及Tokenizer如何写。Analyzer需要一个Tokenizer来进行切词,所以还需要定义一个自己的Tokenizer。 1、先从Analyzer开始 Lucene版本为5.5以上 定义自己的Analyzer需要继承org.apache.lucene.analysis.Analyzer,并且实现TokenStreamComponents createComponents(String s)方法。咱们的Analyzer名字叫DemoAnalyzer。上代码: import org.apache.lucene.analysis.Analyzer; public class DemoAnalyzer extends Analyzer { @Override protected TokenStreamComponents createComponents(String s) { return new TokenStreamComponents( new DemoTokenizer() ); } } 在createComponents方法里面直接new一个TokenStreamComponents对象,对象里面包含的是自定义的DemoTokenizer对象,主要的分词工作就是在这个类里面完成。 2、定义Tokenizer 自定义的Tokenizer需要继承org.apache.lucene.analysis.Tokenizer,并且实现boolean incrementToken()方法。这个方法比较特殊: 此方法并不是一次性调用,而是进行的迭代调用,也就是说一次是读取一个分词,第二次再读取下一个分词,依次类推。 需要一系列的Attribute来存放对应的一个分词(也就是term)的信息,包括词本身、类型(type),位置,词的始末偏移量等等。这个是通过调用addAttribute方法实现的。 input这个Reader并不需要自己传入,这个就是输入的需要分词的文本在父类已经实现了setReader(Reader input)方法,Lucene自己会调用此方法传入文本 看代码 import org.apache.lucene.analysis.Tokenizer; import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; import org.apache.lucene.analysis.tokenattributes.OffsetAttribute; import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute; import org.apache.lucene.analysis.tokenattributes.TypeAttribute; import java.io.IOException; // 自定义的DemoTokenizer需要继承org.apache.lucene.analysis.Tokenizer类 // 并实现incrementToken和reset方法,这个方法相当于一个iterator方法,Lucene框架会不停的调用这个方法 // 直到这个方法返回false。调用这个对象的大致的伪代码逻辑如下: // obj = new DemoTokenizer(input); // notEnd? = obj.incrementToken(); // if notEnd? { // read attributes from obj // } // attributes表示在这人类里面调用addAttribute方法添加的attribute,包括分出来的词,类型,位置等等 public class DemoTokenizer extends Tokenizer { // 保存当前读取的字符位置信息 private int position = 0; // 保存分出来的词 protected CharTermAttribute charAttr = addAttribute(CharTermAttribute.class); // 保存当前分出来的词的类型,可以随便定义 protected TypeAttribute typeAttr = addAttribute(TypeAttribute.class); // 保存当前词的位置 private final PositionIncrementAttribute positionAttr = addAttribute(PositionIncrementAttribute.class); // 保存当前词的偏移量 private final OffsetAttribute offsetAtt = addAttribute(OffsetAttribute.class); @Override public boolean incrementToken() throws IOException { // 调用这个方法很重要,必须在下面设置attributes之前调用 clearAttributes(); // 保存当前读取到的字符 char[] c = new char[1]; // 读取一个字符到变量c里面 int count = this.input.read(c, this.position, 1); // 返回false代表读完了 if (count == -1) { return false; } // 把当前读取到的字符保存到定义的attributes charAttr.append(c[0]); typeAttr.setType("Char"); positionAttr.setPositionIncrement(position+1); offsetAtt.setOffset(correctOffset(position), correctOffset(position+1)); // 返回true表示后面还有词需要处理,当前还没有读完 return true; } // 正确覆写此方法也非常重要,因为在Lucene框架外面很有可能这个类只会被初始化一次 // 所以如果使用的一些位置信息不正确会导致读取对应的位置错误 @Override public void reset() throws IOException { super.reset(); // 需要把上一个字段使用过的位置信息归0,否则当前这个字段的位置是不正确的 this.position = 0; } } 首先在类的内容需要几个存放Attribute的属性,比如CharTermAttribute charAttr,在调用incrementToken的时候需要先清空再append进charAttr。 ...

October 1, 2017

Lucene7实践入坑第一步

这是一篇很简单的使用Lucene7.0.0来建立索引和搜索的文章。 import org.apache.lucene.analysis.core.WhitespaceAnalyzer; import org.apache.lucene.document.*; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.index.Term; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.PhraseQuery; import org.apache.lucene.search.SearcherManager; import org.apache.lucene.search.TopDocs; import org.apache.lucene.store.FSDirectory; import java.io.IOException; import java.nio.file.Paths; public class UseLucene2 { public static void main(String[] args) throws IOException { FSDirectory indexDir = FSDirectory.open(Paths.get("index")); IndexWriterConfig iwc = new IndexWriterConfig(new WhitespaceAnalyzer()); iwc.setOpenMode(IndexWriterConfig.OpenMode.CREATE); IndexWriter indexWriter = new IndexWriter(indexDir, iwc); DirectoryReader dir = DirectoryReader.open(indexWriter); Document doc = new Document(); doc.add(new StringField("first", "测试", Field.Store.YES)); indexWriter.addDocument(doc); SearcherManager sm = new SearcherManager(indexWriter, true, true, null); PhraseQuery.Builder builder = new PhraseQuery.Builder(); builder.add(new Term("first", "测试")); PhraseQuery pq = builder.build(); IndexSearcher searcher = sm.acquire(); TopDocs docs = searcher.search(pq, 1); System.out.println(docs.totalHits); for (int i = 0; i < docs.totalHits; i++) { System.out.println(docs.scoreDocs[i]); } sm.close(); indexWriter.close(); } } // TODO 补充解释

August 27, 2017

Make your own Emacs package

Make you own Emacs package. 创建自己的Emacs包。 在Elpa、MELPA上面有许多的包,可以做各种各样的事情,但有可能你找不到一个合适你的某个问题的包,这时候可以自己动手写一个package,分离到MEELPA。 其实写一个package是一个比较简单的事情,但是又比较麻烦,麻烦在于有很多的约定需要了解,下面我们来动手写一个简单的闹钟包,参考了alarm.el。恰好我的包也叫做alarm.el,如有疑问请提出。 准备 开发阶段使用package-insstall-file来安装并且测试包是否正确,这个命令可以安装单个文件something.el,也可以安装一个tar包,这里主要有两个文件,所以需要打成tar包安装。 目录结构 alarm-20170724.1502 |-alarm-pkg.el |-alarm.el |-alarm.wav 目录名的命名规则是name-version alarm-pkg.el 是给emacs的package提供信息的一个文件 alarm.el 程序主要内容在这个文件 alarm.wav 闹钟响的时候播放这个文件,还可以使用.au文件 alarm-pkg.el (define-package "alarm" "20170724.1502" "A package to alarm yourself at some time.") 这个文件比较简单,只是调用了define-package来定义你的包信息,此函数的签名如下: (defun define-package (_name-string _version-string &optional _docstring _requirements &rest _extra-properties) (error "Don't call me!")) 第一个参数是包名,第二个参数是版本号,第三个参数可以是一个长字符串提供说明文档 alarm.el 这个文件的约定比较多,先看一下这个文件的头部 ;;; alarm.el --- Alarm ;; Copyright (C) 2017, Emacs guys, all rights reserved. ;; Author: Kevim Jiang <wenlin1988@126.com> ;; Version: 20170724.1502 ;; Keywords: alarm ;; Maintainer: Kevin Jaing <wenlin1988@126.com> ;; Created: 2017-07-24 12:00:00 ;;; Commentary: ;; Set an alarm with `alarm-clock', and enter the time; ;; cancel the alarm with `alarm-clock-cancel' ;;; Code: 每一个段落以空白行隔开。第一行是文件名和一个简短的说明,而且开头以;;;三个分号注释。Commentary一段可以是长一些的说明文档,以及使用说明。最后是;;; Code:段,接下面就是真正的代码内容。可以使用checkdoc来检查头部的文档是否正确。还可以使用package-lint包的package-lint-current-buffer命令检查。 ...

July 24, 2017

nfs安装配置

记录一下nfs的安装配置以备忘 环境 server CentOS Linux release 7.3.1611 client CentOS Linux release 7.2.1511 Server 安装 yum install -y nfs-utils rpcbind 修改配置文件/etc/expots /opt/tmp *(rw,sync) 启动nfs server端 sudo systemctl start rpcbind sudo systemctl start nfs Client mkdir tmp sudo mount -t nfs 10.123.4.215:/opt/tmp tmp

June 30, 2017

windows下virtualbox里centos挂载共享目录

环境 Windows 10 Virtualbox 5.1.18 CentOS 6.6 minimal 依赖 virtualbox的增强功能需要用到linux的源码,所以需要先把linux的开发包装上,还有编译工具。还需要把开发包目录链接到/usr/src/linux: yum install kernel-devel kernel-devel-$(uname -r) gcc perl ln -s /usr/src/kernels/2.6.32-696.3.2.el6.x86_64 /usr/src/linux Ubuntu sudo apt-get install linux-headers-$(uname -r) 安装 首先得把centos安装好,然后挂载好增强功能的iso文件(VBoxGuestAdditions.iso)–选择菜单设备->安装增强功能 然后在centos挂载iso文件,执行安装程序: sudo mkdir /media/cdrom sudo mount /dev/cdrom /media/cdrom sudo cd /media/cdrom sudo ./VBoxLinuxAdditions.run 如果没有error说明安装成功,如果有关于X的错误,有可能是你没有安装X环境,如果只是使用命令行,这个也不用管。安装完增强功能后最好把centos重启一下。 配置共享目录 首先设置windows到centos的共享目录,在virtualbox的设置->共享文件夹添加对应的目录 这里有一个共享文件夹名称,这个名称可以直接在centos里面使用。然后在centos挂载这个目录: cd ~ mkdir folder mount -t vboxsf workspace folder mount只有有root权限的才可以执行,如果是普通用户使用sudo,修改/etc/sudoers,把下面一行的注释去掉: # %wheel ALL=(ALL) ALL # -> 去掉注释变成下面的 %wheel ALL=(ALL) ALL 然后把普通用户(我这里是www用户)加入到wheel组即可使用sudo usermod -a -G wheel www 到这已经把共享目录挂载完成了。如果不想每次都手动挂载,就把这个挂载写到/etc/fstab文件里,每次开机自动挂载: ...

June 28, 2017

记一次php5.3.10安装

安装环境 CentOS 6.6 x64 php 5.3.10 安装编译工具 yum install -y gcc gcc-c++ 安装mysql yum install -y mysql mysql-devel #如果是64位系统,执行 ln -s /usr/lib64/mysql/* /usr/lib/ 安装依赖 yum install -y libxml2-devel openssl-devel libcurl-devel libjpeg-turbo-devel libpng-devel freetype-devel openldap-devel cyrus-sasl-ldap libtool libtool-ltdl-devel #如果是64位系统,执行 ln -s /usr/lib64/libldap* /usr/lib/ ln -s /usr/lib64/mysql/* /usr/lib/ openldap-devel 这个在我工作的项目当中使用到了,如果不需要这个可以不要安装这个 安装php curl -o php-5.3.10.tar.gz 'http://museum.php.net/php5/php-5.3.10.tar.gz' tar xzvf php-5.3.10.tar.gz cd php-5.3.10 ./configure --prefix=/usr/local/php-5.3.10 --with-config-file-path=/usr/local/php-5.3.10/etc --with-mysql --with-mysqli=mysqlnd --with-pdo-mysql --with-iconv-dir=/usr/local --with-freetype-dir --with-jpeg-dir --with-png-dir --with-zlib --with-libxml-dir --enable-xml --enable-safe-mode --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --with-curlwrappers --enable-mbregex --enable-fpm --enable-mbstring --with-mcrypt --with-gd --enable-gd-native-ttf --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-ldap --with-ldap-sasl --with-xmlrpc --enable-zip --enable-soap make make install ln -s /usr/local/php-5.3.10 /usr/local/php 启动脚本 使用下面的脚本需要修改php-fpm.conf,把pid那行的注释去掉 ...

June 27, 2017

Racket开发环境Emacs配置

首先到Racket官网下载安装包,然后你还需要Emacs。 在Emacs安装rakcet-mode,M-x输入package-install,再输入racket-mode。安装完后在 init.el 初始化文件添加下面配置: (when (package-installed-p 'racket-mode) (setq racket-racket-program "C:/Program Files/Racket/Racket.exe") (setq racket-raco-program "C:/Program Files/Racket/raco.exe")) 把 C:/Program Files/Racket/ 改成对应的自己机器对应的路径即可。 如果是Linux或者maxOS系统,相应的程序应该是racket和raco。

June 23, 2017