我有一个MongoDB,其中包含一系列文档:
{
_id: ObjectId("5222769532fed3037d000049"),
cat_list: { "52226a8932fed36c3000007e": 1 },
feature_list: {
"52227433abb03fa34b0000fa": 0.2,
"52236117099c8924c500004a": 0.2,
"52236236c71890c199000054": 0.2,
"522374d2842e497d2c00000c": 0.2,
"52237e3b842e493760000021": 0.2 },
title: "blah"
}
现在我基本上想找到与feature_list
内的密钥提供的一组密钥匹配的文档。为此,我想我将使用某种形式的[,],但是我不确定如何使用键:值列表。 (它是一样的吗?)
其次,我想按降序频率排序结果(如果我可以在mongodb中执行此操作而无需在我的服务器端代码中执行此操作)。因此,如果我查询"52227433abb03fa34b0000fa" OR "52236117099c8924c500004a" OR "52236236c71890c199000054"
,我的结果集将包含所有具有feature_list的文档,其中包含OR列表中的一个或多个,并且首先是匹配量最大的文档,然后是接下来的频率等等。
答案 0 :(得分:2)
要使用至少一个具有给定值的字段查找所有这些文档,您可以使用此查询:
db.aggr.find({$or: [
{ "feature_list.52227433abb03fa34b0000fa" : { $exists: true } },
{ "feature_list.52236117099c8924c500004a" : { $exists: true } },
{ "feature_list.52236236c71890c199000054" : { $exists: true } }
]});
找到你的文件:
{
"_id" : ObjectId("5222769532fed3037d000049"),
"cat_list" : {
"52226a8932fed36c3000007e" : 1
},
"feature_list" : {
"52227433abb03fa34b0000fa" : 0.2,
"52236117099c8924c500004a" : 0.2,
"52236236c71890c199000054" : 0.2,
"522374d2842e497d2c00000c" : 0.2,
"52237e3b842e493760000021" : 0.2
},
"title" : "blah"
}
但你不能按照你想要的方式对它进行排序,因为没有任何可排序的东西。我正在考虑按所有这些搜索字段进行排序,如果只搜索一个字段,它会起作用,因为缺少的字段会有lowest value。但是,在这种情况下,对于多个字段,sort
中字段的顺序很重要,这个技巧不起作用。
什么也行不通的是尝试按整个子文档排序,即.sort({"feature_list" : -1})
因为它没有给出任何有意义的排序。
所以在这一点上获得这些结果的唯一方法是使用聚合框架,多个查询(例如3个),或者在代码中执行此操作。
我很确定我可以写一个聚合框架查询来做到这一点,但首先你会受到单个文档大小(32Mb)中可以容纳的结果数量的限制。如果你只返回id,那就更好了。其次,它实际上可能不是那么有效。最后,您可能需要考虑重新设计架构,因为它非常传统。这样查询会很困难,也很低效。
修改强>
可以像这样重新设计架构:
{ ...,
feature_list: [
{fid: "52227433abb03fa34b0000fa", weight: 0.2},
{fid: "52236117099c8924c500004a", weight: 0.2}
]
}
这仍然无助于使用常规查询进行排序,但是查找数据会快得多,因为Mongo不使用$exists
的索引,但会在这个新架构中使用索引(如果存在),其中字段变为数据。没有办法按照数组中匹配元素的数量对Mongo进行排序。
您可以使用聚合框架而不是常规查询以非常类似的方式获取数据: In MongoDB search in an array and sort by number of matches 问题是您只能使用聚合框架获得尽可能多的结果。为了充分利用它,您可以在最后的步骤中仅投影文档的_id。
使用聚合框架的替代方法是在找到结果后对代码中的数据进行排序。在任何一种情况下,由于索引,模式重新设计似乎都是有益的。