我有一个应用程序 (nodejs/express) 需要根据一天中的时间和星期几找到要应用的路由规则。
例如,我有以下业务规则:
(为了讨论的目的,ABC 是什么对象并不重要。)
我在两种选择之间争论,至于我应该如何在我的 REDIS 数据库中设计我的键
选项 1
将日期信息作为对象数据的一部分,如下所示:
HMSET routing_rules:objectABC_09:00_12:00 days 'mon tues' location X
HMSET routing_rules:objectABC_13:00_13:30 days 'tues' location Y
这种方法的优点 - 当需要更新天数列表时,我可以简单地这样做:
HMSET routing_rules:objectABC_09:00_12:00 days 'mon tues thu'
这里的缺点是为了找到正确的规则,我必须进行两次查询......首先执行 SCAN 命令以找到正确的时间范围......然后如果有匹配......做另一个查找天数的查询。
选项 2
将星期几信息作为 key 的一部分
HMSET routing_rules:objectABC_09:00_12:00_mt location X
HMSET routing_rules:objectABC_13:00_13:30_t location Y
我会使用这样的命名约定
m = monday
t = tuesday
w = wed
r = thursday
etc.
选项 2 的优点是,为了根据当前时间和日期找到正确的路由规则,我只需要运行一个 SCAN 命令(我们可以假设我的 SCAN 命令会一次性返回所有结果)
但选项 2 的缺点是,当我需要向键添加新的一天时,我认为我需要删除键和值...然后重新创建它。这个对吗?
截至目前,我知道如何删除的唯一方法是为对象中的每个值执行 HDEL,然后删除键。 因此,例如,我一直在做这样的事情:
127.0.0.1:6379> HDEL routing_rules:objectABC_00:00_00:00 days 'mon tues' location x
我必须在其中列出对象中的所有值才能删除整个键/值对。 在这个例子中,还不错,因为我只有这个键的两个值——位置和天数字段。但是如果有更多的数据,那就有点麻烦了。而且我不确定除了与此键关联的字段数之外是否还有其他考虑因素。
如果您对如何设计此 key 以获得最佳性能和维护有任何建议,我会洗耳恭听。在我看来,没有办法避免至少运行一次扫描。但这是我第一次尝试 redis 数据库,所以我提前为补救问题/菜鸟错误道歉。
编辑 1
假设我有足够的内存并假设我只需要为每个键保存一个字段/值,假设我这样创建我的键:
SET routing_rules:objectABC_09:00_12:00_m X
SET routing_rules:objectABC_09:00_12:00_t X
SET routing_rules:objectABC_13:00_13:30_t Y
现在收到对象 ABC 的请求,它是星期一的 UTC 11。因为我的键代表开始时间和结束时间(也称为范围),所以我不知道如何找到正确的键/值对做扫描。
我错过了什么吗?
最佳答案
我会采用排序集解决方案,每个对象一个集合,值应该是位置*,分数应该是该规则到期的那一周的分钟数。
例如(一周从星期一 00:00 开始)
on Mondays and Tuesdays between 09:00 GMT and 12:00 GMT, I need route object ABC to "location x".
周一 12:00 => 720 星期二 12:00 => 2160
ZADD ABC_rules 720 x 2160 x
这里有两个问题,第一个是您的示例多次显示没有规则,因此必须考虑到这一点。第二大,集合对象必须是唯一的,x不能存储两次。两者都是上面的 * 原因,解决它的方法是在规则开始的那一周的分钟内添加/添加值:
周一 9:00 => 540 星期二 9:00 => 1980
ZADD ABC_rules 720 x:540 2160 x:1980
要查询,您只需将 ZRANGEBYSCORE 与星期中的分钟一起使用,并确保附加到该位置的时间早于您发送的时间。
周一 10:00(600)的查询:
ZRANGEBYSCORE ABC_rules 600 +inf LIMIT 1
结果将是 x:540,因为 540 小于 600,您知道 x 是一个有效答案。
周一13:00(780)的查询:
ZRANGEBYSCORE ABC_rules 780 +inf LIMIT 1
结果将是 x:1980,并且由于 1980 大于您的查询 (780),因此该结果无效,您应该采用默认路由(或您对未映射时间的任何解决方案在你的日程安排中)。
要删除规则,您必须删除附加有开始时间的位置:
ZREM ABC_rules x:540
您还可以使用 ZRANGEBYSCORE 获取特定日期适用的所有规则,您可以编写清除它们的 LUA 脚本。
关于node.js - REDIS - 创建有意义的键以减少查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39799007/
我正在用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
我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案
查看我的Ruby代码:h=Hash.new([])h[0]=:word1h[1]=h[1]输出是:Hash={0=>:word1,1=>[:word2,:word3],2=>[:word2,:word3]}我希望有Hash={0=>:word1,1=>[:word2],2=>[:word3]}为什么要附加第二个哈希元素(数组)?如何将新数组元素附加到第三个哈希元素? 最佳答案 如果您提供单个值作为Hash.new的参数(例如Hash.new([]),完全相同的对象将用作每个缺失键的默认值。这就是您所拥有的,那是你不想要的。您可以改用
点向量坐标矩阵的几何意义介绍旋转矩阵的几何含义之前,先介绍一下点向量坐标矩阵的几何含义点:在一维空间下就是一个标量,如同一条直线上,以任意某一个位置为0点,以一定的尺度间隔为1,2,3...,相反方向为-1,-2,-3...;如此就形成了一维坐标系,这时候任何一个点都可以用一个数值表示,如点p1=5,即即从原点出发沿着x轴正方向移动5个尺度;点p2=-3,负方向移动3个尺度; 在一维坐标系上过原点做垂直于一维坐标系的直线,则形成了二维坐标系,此时描述一个点需要两个数值来表示点p3=(3,2),即从原点出发沿着x轴正方向移动3个尺度,在此基础上沿着y轴正方向移动两个尺度的位置就是点p3。
我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时
因此,对于普通哈希,您可以使用它来获取key:hash.keys如何获取如下所示的多维哈希的第二维键:{""=>{"first_name"=>"test","last_name"=>"test_l","username"=>"test_user","title"=>"SalesManager","office"=>"test","email"=>"test@test.com"}}每个项目都是唯一的。所以我想从上面得到的键是:first_name,last_name,username,title,officeandemail 最佳答案
我在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*')(顾名思义)作为过滤器查询应用,因此不参与评分。似乎可以手动编写字符串(或者可能使