我如何模仿mongoid和ruby中的“SELECT _id”?

时间:2012-07-05 17:22:20

标签: mongodb mongoid

目前我正在做以下事情:

    responses = Response.where(user_id: current_user.uid)
    qids = []
    responses.each { |r| qids << r._id}
    return qids

有更好的方法吗?

3 个答案:

答案 0 :(得分:2)

使用.only()检索更少的数据。

quids = Response.only(:_id).where(user_id: current_user.uid).map(&:_id)

答案 1 :(得分:0)

Response.where(user_id: current_user.uid).map { |r| r._id }

这有点像惯用语。

就mongoid而言,mongoid提供的唯一“映射”类型功能是自定义map-reduce滤镜。您可以查看documentation

在这种情况下,编写这样的过滤器对您没有好处。您正在加载整个数据集(延迟加载没有帮助)并且您没有减少任何内容。

答案 2 :(得分:0)

直截了当地解决这个问题

如果您想获取结果集中唯一的id或内容,那么它在功能上等同于使用distinct方法。这样你就可以保存映射操作,而且它看起来要快得多(测试以及为什么你应该采取一些预防措施来解决它们的问题)。

Response.where(user_id: current_user.uid).distinct(:_id)

因此,如果您想获得非独特的东西,并且出于某种原因想要获得重复的结果,那么只能使用它。即如果您的回复可能会被喜欢,并且您想获得所有喜欢的数组(假设您想要计算一些有关喜欢的统计数据):

Response.where(user_id: current_user.uid).map { |r| r.likes }



测试...

这是一些随机测试,但是对于更值得信赖的结果,应该使用大型数据库提交测试,而不是重复操作。我的意思是,我知道可以有任何类型的优化来重复重复相同的查询(显然地图不能有任何这样的优化)。

Benchmark.measure { 1000.times { Organization.where(:event_labels.ne =[]).map(&:_id) } }
=>   6.320000   0.290000   6.610000 (  6.871498)
Benchmark.measure { 1000.times { Organization.where(:event_labels.ne => []).only(:_id).map(&:_id) } }
 =>   5.490000   0.140000   5.630000 (  5.981122)
Benchmark.measure { 1000.times { Organization.where(:event_labels.ne => []).distinct(:_id) } }
=>   0.570000   0.020000   0.590000 (  0.773239)
Benchmark.measure { 1000.times { Organization.where(:event_labels.ne => []).only(:_id) } }
=>   0.140000   0.000000   0.140000 (  0.141278)
Benchmark.measure { 1000.times { Organization.where(:event_labels.ne => []) } }
=>   0.070000   0.000000   0.070000 (  0.069482)

在没有map的情况下执行only需要更长的时间,因此使用only是有益的。虽然使用它似乎实际上略微损害了性能,如果你根本不做map,但拥有较少的数据似乎会使map运行得更快一些。无论如何,根据这个测试,似乎distinct在所有指标(用户,系统,总数,实际)上比使用onlymap组合快10倍,尽管它比使用only而不使用map