1 Redis查询
首先介绍下RedisMod这个东西,它是一系列Redis的增强模块。有了RedisMod的支持,Redis的功能将变得非常强大。目前RedisMod中包含了如下增强模块:
RediSearch:一个功能齐全的搜索引擎;RedisJSON:对JSON类型的原生支持;RedisTimeSeries:时序数据库支持;RedisGraph:图数据库支持;RedisBloom:概率性数据的原生支持;RedisGears:可编程的数据处理;RedisAI:机器学习的实时模型管理和部署。Redis这些模块都是依赖于Redis,因此先要安装Redis
点击了解Redis单机安装
点击了解Redis集群安装
下载RediSearch+RedisJSON地址:https://redis.com/redis-enterprise-software/download-center/software/

redis 安装目录下新建 module 文件夹,把获取到的rejson.so和module-enterprise.so(可以重命名为redissearch.so)文件 放到 module 文件夹中
修改 文件 为可执行权限
chmod +x rejson.so
chmod +x module-enterprise.so
修改 redis.conf,搜索 loadmodule
loadmodule /root/software/redis-6.0.6/module/rejson.so
loadmodule /root/software/redis-6.0.6/module/module-enterprise.so
重启 redis
/usr/local/redis-6.2.6/bin/redis-cli -a 123456 shutdown
/usr/local/redis-6.2.6/bin/redis-server conf/redis.conf
命令行体验 json 的操作
语法:
JSON.SET <key> <path> <json> [NX | XX]
参数说明:
Key,path需要使用$或 .
Key,在进行保存操作之后,原来path路径的值将会被替换掉;NX:表示只有Key不存在,才执行保存操作XX:表示只有Key存在,才执行保存操作type doc可以查看到存储进去的数据是ReJSON-RL类型语法:
JSON.GET <key>
[INDENT indentation-string]
[NEWLINE line-break-string]
[SPACE space-string]
[path ...]
参数说明:
path进行查询INDENT 查询结果替换掉默认缩进字符(用于返回Pretty-formatted JSON)NEWLINE 查询结果替换掉默认换行符(用于返回Pretty-formatted JSON)SPACE 查询结果替换掉默认空格(用于返回Pretty-formatted JSON)JSON对象中的属性时需要以.开头语法:
JSON.MGET <key> [key ...] <path>
参数说明:
path进行处理Key的path,如果不存在,则返回null
例子:
先保存两条记录
JSON.SET doc1 $ '{"a":1, "b": 2, "nested": {"a": 3}, "c": null}'
JSON.SET doc2 $ '{"a":4, "b": 5, "nested": {"a": 6}, "c": null}'
再进行mget操作
JSON.MGET doc1 doc2 $..a
执行结果:
1) "[1,3]"
2) "[4,6]"
语法:
JSON.DEL <key> [path]
参数说明:
path是可选的,如果没有输入,则默认整个Key删除掉例子:
JSON.DEL doc $..a
结果:
"2"
除了上面的几种常见操作,官方还支持如下命令,官方命令地址:https://redis.io/docs/stack/json/commands/
常用命令:
JSON.NUMINCRBY,JSON.NUMMULTBY,JSON.STRAPPEND,JSON.STRLEN
数组命令:
JSON.ARRAPPEND,JSON.ARRINDEX,JSON.ARRINSERT,JSON.ARRLEN,JSON.ARRPOP,JSON.ARRTRIM
对象命令:
JSON.OBJKEYS,JSON.OBJLEN
组件命令
JSON.TYPE,JSON.DEBUG,JSON.FORGET,JSON.RESP
创建一个 json_1
127.0.0.1:6379> JSON.SET json_1 . '{"name":"zz","age":22,"msg":"hello"}'
OK
设置 json_1 的 key=name 的值为 zhangsan
127.0.0.1:6379> JSON.SET json_1 .name '"zhangsan"'
OK
获得整个 json_1
127.0.0.1:6379> JSON.GET json_1
"{\"name\":\"zhangsan\",\"age\":22,\"msg\":\"hello\"}"
获得 json_1 键为 name 的值
127.0.0.1:6379> JSON.GET json_1 .name
"\"zhangsan\""
往 json_1 中添加一个数组对象
127.0.0.1:6379> json.set json_1 .list '[2,3,4]'
OK
往 json_1 的 list 对象中添加一个元素 6
127.0.0.1:6379> json.arrappend json_1 .list 6
(integer) 4
查看所有元素
127.0.0.1:6379> json.get json_1
"{\"name\":\"zhangsan\",\"age\":22,\"msg\":\"hello\",\"list\":[2,3,4,6]}"
体验下来,感觉 Redis 原生支持 json 之后,对于 redis 的操作更加灵活了。
想象空间更大了,一切复杂信息的存储皆可 JSON,并且操作十分简单,省去了序列化、反序列化的操作,
当然我们还是要在一个 Java 工程中去操作一下:
package com.kkarch.rejson;
import com.redislabs.modules.rejson.JReJSON;
import com.redislabs.modules.rejson.Path;
import redis.clients.jedis.Jedis;
import java.util.Arrays;
public class ReJsonMain {
public static void main(String[] args) {
Jedis jedis = new Jedis("192.168.0.110",6379);
jedis.auth("123456");
JReJSON redisClient = new JReJSON(jedis);
System.out.println("初始化 json");
redisClient.set("json_2",new Object());
redisClient.set("json_2","zhangsan",new Path(".name"));
redisClient.set("json_2",21,new Path(".age"));
redisClient.set("json_2","hello",new Path(".msg"));
redisClient.set("json_2",Arrays.asList(9,8,7),new Path(".arr"));
Object result = null;
result = redisClient.get("json_2");
System.out.println(result);
System.out.println("设置 name=lisi");
redisClient.set("json_2","lisi",new Path(".name"));
result = redisClient.get("json_2");
System.out.println(result);
System.out.println("在数组追加一个值:21");
redisClient.arrAppend("json_2", new Path(".arr"), 21);
result = redisClient.get("json_2");
System.out.println(result);
}
}
结果:
初始化 json
{name=zhangsan, age=21.0, msg=hello, arr=[9.0, 8.0, 7.0]}
设置 name=lisi
{name=lisi, age=21.0, msg=hello, arr=[9.0, 8.0, 7.0]}
在数组追加一个值:21
{name=lisi, age=21.0, msg=hello, arr=[9.0, 8.0, 7.0, 21.0]}
通过RediSearch模块,Redis可以变成一个功能强大的全文搜索引擎,并且原生支持中文搜索,下面我们就来体验下
RediSearch的搜索语法比较复杂,不过我们可以对比SQL来使用它,具体可以参考如下

| SQL Condition | RediSearch Equivalent | 注释 |
|---|---|---|
| where x='foo' and y='bar' | @x:foo @y:bar | for less ambiguity use (@x:foo) (@y:bar) |
| where x='foo' and y!='bar' | @x:foo -@y:bar | |
| where x='foo' or y='bar' | (@x:foo) | (@y:bar) | |
| where x in ('foo' ,'bar' ) | @x:(foo| bar) | quotes means exact phrase |
| where y='foo' and x not in ('foo' ,'bar' ) | @y:foo (-@x:foo)(-@x:bar) | |
| where num between 10 and 20 | @num:[10:20] | |
| where num >=10 | @num:[10 +inf] | |
| where num > 10 | @num:[(10 +inf] | |
| where num < 10 | @num:[-inf (10] | |
| where num <= 10 | @num:[-inf 10] | |
| where num < 10 or num >20 | @num:[-inf (10] | @num:[(20 +inf ] | |
| where name like 'john%' | @name:john* |
使用 RediSearch 来搜索数据之前,我们得先创建下索引,建立索引的语法有点复杂,我们先来看下;
FT.CREATE {index}
[ON {data_type}]
[PREFIX {count} {prefix} [{prefix} ..]
[LANGUAGE {default_lang}]
SCHEMA {identifier} [AS {attribute}]
[TEXT | NUMERIC | GEO | TAG ] [CASESENSITIVE]
[SORTABLE] [NOINDEX]] ...
使用FT.CREATE命令可以建立索引,语法中的参数意义如下;
index:索引名称;data_type:建立索引的数据类型,目前支持JSON或者HASH两种;PREFIX:通过它可以选择需要建立索引的数据前缀,比如PREFIX 1 "product:" 表示为键中以product:为前缀的数据建立索引;LANGUAGE:指定TEXT类型属性的默认语言,使用chinese可以设置为中文;SCHEMA:索引的字段identifier:指定属性名称;attribute:指定属性别名;TEXT | NUMERIC | GEO | TAG:这些都是属性可选的类型;SORTABLE:指定属性可以进行排序。看了语法可能不太好理解,直接对一个商品数据建立索引试试就懂了;
FT.CREATE
productIdx
ON JSON
PREFIX 1 "product:"
LANGUAGE chinese
SCHEMA $.id AS id NUMERIC
$.name AS name TEXT $.subTitle AS subTitle TEXT
$.price AS price NUMERIC
SORTABLE $.brandName AS brandName TAG
建立完索引后,我们就可以使用FT.SEARCH对数据进行查看了,比如使用*可以查询全部;
FT.SEARCH productIdx *
由于我们设置了price字段为SORTABLE,我们可以以price降序返回商品信息
FT.SEARCH productIdx * SORTBY price DESC
指定返回的字段;
FT.SEARCH productIdx * RETURN 3 name subTitle price
我们把brandName设置为了TAG类型,我们可以使用如下语句查询品牌为小米或苹果的商品;
FT.SEARCH productIdx '@brandName:{小米 | 苹果}'
由于price是NUMERIC类型,我们可以使用如下语句查询价格在500~1000的商品;
FT.SEARCH productIdx '@price:[500 1000]'
还可以通过前缀进行模糊查询,类似于SQL中的LIKE,使用*表示;
FT.SEARCH productIdx '@name:小米*'
在FT.SEARCH中直接指定搜索关键词,可以对所有TEXT类型的属性进行全局搜索,支持中文搜索,比如我们搜索下包含黑色字段的商品;
FT.SEARCH productIdx '黑色'
当然我们也可以指定搜索的字段,比如搜索副标题中带有红色字段的商品;
FT.SEARCH productIdx '@subTitle:红色'
通过FT.DROPINDEX命令可以删除索引,如果加入DD选项的话,会连数据一起删除;
FT.DROPINDEX productIdx
通过FT.INFO命令可以查看索引状态;
FT.INFO productIdx
我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.
我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时
我在Rails上使用带有ruby的solr。一切正常,我只需要知道是否有任何现有代码来清理用户输入,比如以?开头的查询。或* 最佳答案 我不知道执行此操作的任何代码,但理论上可以通过查看parsingcodeinLucene来完成并搜索thrownewParseException(只有16个匹配!)。在实践中,我认为您最好只捕获代码中的任何solr异常并显示“无效查询”消息或类似信息。编辑:这里有几个“sanitizer”:http://pivotallabs.com/users/zach/blog/articles/937-s
我正在为锦标赛开发一个Rails应用程序。我在这个查询中使用了三个模型:classPlayertruehas_and_belongs_to_many:tournamentsclassTournament:destroyclassPlayerMatch"Player",:foreign_key=>"player_one"belongs_to:player_two,:class_name=>"Player",:foreign_key=>"player_two"在tournaments_controller的显示操作中,我调用以下查询:Tournament.where(:id=>params
我想用sunspot重现以下原始solr查询q=exact_term_text:fooORterm_textv:foo*ORalternate_text:bar*但我无法通过标准的太阳黑子界面理解这是否可能以及如何实现,因为看起来:fulltext方法似乎不接受多个文本/搜索字段参数我不知道将什么参数作为第一个参数传递给fulltext,就好像我通过了"foo"或"bar"结果不匹配如果我传递一个空参数,我得到一个q=*:*范围过滤器(例如with(:term).starting_with('foo*')(顾名思义)作为过滤器查询应用,因此不参与评分。似乎可以手动编写字符串(或者可能使
例如,假设我有一个名为Products的模型,并且在ProductsController中,我有以下代码用于product_listView以显示已排序的产品。@products=Product.order(params[:order_by])让我们想象一下,在product_listView中,用户可以使用下拉菜单按价格、评级、重量等进行排序。数据库中的产品不会经常更改。我很难理解的是,每次用户选择新的order_by过滤器时,rails是否必须查询,或者rails是否能够以某种方式缓存事件记录以在服务器端重新排序?有没有一种方法可以编写它,以便在用户排序时rails不会重新查询结果
我目前正在尝试了解RoR。我将两个字符串传递到我的Controller中。一个是随机的十六进制字符串,另一个是电子邮件。该项目用于对数据库进行简单的电子邮件验证。我遇到的问题是当我输入如下内容来测试我的页面时:http://signup.testsite.local/confirm/da2fdbb49cf32c6848b0aba0f80fb78c/bob.villa@gmailcom我在:email的参数散列中得到的全部是'bob'。我在gmail和com之间留下了.,因为那样会导致匹配根本不起作用。我的路由匹配如下:match"confirm/:code/:email"=>"conf
我正在寻找一种方便实用的方法来将编码值添加到Ruby中的URL查询字符串。目前,我有:require'open-uri'u=URI::HTTP.new("http",nil,"mydomain.example",nil,nil,"/tv",nil,"show="+URI::encode("Rosie&Jim"),nil)pu.to_s#=>"http://mydomain.example/tv?show=Rosie%20&%20Jim"这不是我要找的,因为我需要得到“http://mydomain.example/tv?show=Rosie%20%26%20Jim”,这样show=值就