草庐IT

MongoDB:在给定行之前和之后按顺序返回行?

coder 2023-05-05 原文

在 MongoDB 中,给定一个 find() 运算符,它返回一组行的游标,返回“上下文”行的惯用且省时的方式是什么,即在每行之前和/或之后按顺序排列的行在集合中?

对我来说,解释这个概念最简单的方法是使用 ack ,它支持上下文搜索。给定一个文件:

line 1
line 2
line 3
line 4
line 5
line 6
line 7
line 8

这是 ack 的输出:

C:\temp>ack.pl -C 2 "line 4" test.txt
line 2
line 3
line 4
line 5
line 6

我将日志数据存储在 MongoDB 集合中,每行一个文档。每个日志都被标记为关键字,并且这些关键字被索引,这给了我廉价的全文搜索。

我执行一个沼泽标准:

collection.find({keywords: {'$all': ['key1', 'key2']}}, {}).sort({datetime: -1});

并获得一个光标。在这个阶段,在不添加任何额外字段的情况下,获取上下文的方法是什么?我认为流程是这样的:

  • 对于游标中的每一行:
    • 获取_id字段,存入x。
    • 执行:collection.find({_id: {'$gt': x}}).limit(N)
      • 从每个游标中获取结果。
    • 执行:collection.find({_id: {'$lt': x}}).sort({_id: 1}).limit(N)
      • 从每个游标中获取结果。

对于具有 R 行的结果集,这需要 2R+1 次查询。

但是,我认为我可以用空间换取时间。在后台使用其上下文_id更新每一行是否可行?对于当前具有字段的给定行:

_id, contents, keywords

我会添加一个额外的字段:

_id, contents, keywords, context_ids

然后在随后的搜索中,我想我可以以某种方式使用这些 context_ids 吗?我对 MongoDB MapReduce 还完全不熟悉,但是这也能理解吗?

我认为最直接的方法是在每一行中存储实际上下文行的全文,但这对我来说似乎有点粗糙。明显的优势是单个查询可以返回我需要的上下文。

我感谢所有接受问题范围的答案。我意识到我可以在带外使用 Lucene 或真正的全文搜索引擎,但我正在尝试感受 MongoDB 的优势和功能,因此我会很感激 MongoDB 特定的答案。谢谢!

最佳答案

我认为您存储 context_ids 或类似的方法可能是最佳选择。如果您能够存储您需要的所有上下文行的 context_ids (假设它是固定大小的上下文量 - 比如说前后 5 行),那么您可以查询对于使用 $in 的所有上下文行:

# pseudocode
for each matching row:
    context_rows = db.logs.find({_id: {$in: row['context_ids']}}).sort({_id: 1})
    row_with_context = [context_rows_before_row] + row + [context_rows_after_row]

我想知道上下文行的集合——尤其是你正在考虑的行之后的行可能很困难,因为任何给定行之后的行不一定存在。

另一种方法可以避免这个问题(但仍然需要一个固定的、预先知道的上下文量)只是将第一行上下文的 _id 存储在相关行之前(即插入时) ,你可以缓冲前面的 N 行,其中 N 是上下文的数量)——调用这个 first_context_id——然后​​像这样查询:

# pseudocode
for each matching row:
    rows_with_context = db.logs.find({_id: {$gte: row['first_context_id']}}).sort({_id: 1}).limit(N * 2 + 1)

这也可以简化您的应用程序逻辑,因为您不需要将上下文与相关行重新组合,此查询将返回匹配的行和上下文的行。

关于MongoDB:在给定行之前和之后按顺序返回行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9533270/

有关MongoDB:在给定行之前和之后按顺序返回行?的更多相关文章

  1. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  2. ruby - Chef 执行非顺序配方 - 2

    我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul

  3. ruby - 如何在 Rails 4 中使用表单对象之前的验证回调? - 2

    我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser

  4. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  5. ruby - Ruby 中的隐式返回值是怎么回事? - 2

    所以我开始关注ruby​​,很多东西看起来不错,但我对隐式return语句很反感。我理解默认情况下让所有内容返回self或nil但不是语句的最后一个值。对我来说,它看起来非常脆弱(尤其是)如果你正在使用一个不打算返回某些东西的方法(尤其是一个改变状态/破坏性方法的函数!),其他人可能最终依赖于一个返回对方法的目的并不重要,并且有很大的改变机会。隐式返回有什么意义?有没有办法让事情变得更简单?总是有返回以防止隐含返回被认为是好的做法吗?我是不是太担心这个了?附言当人们想要从方法中返回特定的东西时,他们是否经常使用隐式返回,这不是让你组中的其他人更容易破坏彼此的代码吗?当然,记录一切并给出

  6. ruby-on-rails - ruby 日期方程不返回预期的真值 - 2

    为什么以下不同?Time.now.end_of_day==Time.now.end_of_day-0.days#falseTime.now.end_of_day.to_s==Time.now.end_of_day-0.days.to_s#true 最佳答案 因为纳秒数不同:ruby-1.9.2-p180:014>(Time.now.end_of_day-0.days).nsec=>999999000ruby-1.9.2-p180:015>Time.now.end_of_day.nsec=>999999998

  7. ruby - 从 String#split 返回的零长度字符串 - 2

    在Ruby1.9.3(可能还有更早的版本,不确定)中,我试图弄清楚为什么Ruby的String#split方法会给我某些结果。我得到的结果似乎与我的预期相反。这是一个例子:"abcabc".split("b")#=>["a","ca","c"]"abcabc".split("a")#=>["","bc","bc"]"abcabc".split("c")#=>["ab","ab"]在这里,第一个示例返回的正是我所期望的。但在第二个示例中,我很困惑为什么#split返回零长度字符串作为返回数组的第一个值。这是什么原因呢?这是我所期望的:"abcabc".split("a")#=>["bc"

  8. ruby - 为什么 Integer.respond_to?( :even? ) 返回 false? - 2

    我一直在研究RubyKoans,我发现about_open_classes.rbkoan很有趣。特别是他们修改Integer#even?方法的最后一个测试。我想尝试一下这个概念,所以我打开了Irb并尝试运行Integer.respond_to?(:even?),但令我惊讶的是我得到了错误。然后我尝试了Fixnum.respond_to?(:even?)并得到了错误。我还尝试了Integer.respond_to?(:respond_to?)并得到了true,当我执行2.even?时,我也得到了true。我不知道发生了什么。谁能告诉我缺少什么? 最佳答案

  9. ruby-on-rails - 在 RSpec 中,如何以任意顺序期望具有不同参数的多条消息? - 2

    RSpec似乎按顺序匹配方法接收的消息。我不确定如何使以下代码工作:allow(a).toreceive(:f)expect(a).toreceive(:f).with(2)a.f(1)a.f(2)a.f(3)我问的原因是a.f的一些调用是由我的代码的上层控制的,所以我不能对这些方法调用添加期望。 最佳答案 RSpecspy是测试这种情况的一种方式。要监视一个方法,用allowstub,除了方法名称之外没有任何约束,调用该方法,然后expect确切的方法调用。例如:allow(a).toreceive(:f)a.f(2)a.f(1)

  10. ruby-on-rails - 如何处理 Grape 中特定操作的过滤器之前? - 2

    我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?

随机推荐