MongoDB比较数组

时间:2016-05-26 15:20:52

标签: mongodb

我有一个拥有数千名用户的集合。每个用户文档都有一些属性,如姓名,年龄范围和收藏夹。

我可以轻松地帮助用户找到同一年龄范围内的其他用户,但我也想以某种方式允许他们选择与其他用户共享的收藏的匹配百分比或数量。

例如

User 1
Name: x
Age Range: 19-25
Favourites: ["Red", "Green", "Blue"]

User 2
Name: y
Age Range: 19-25
Favourites: ["Orange", "Red", "Pink"]

User 3
Name: z
Age Range: 19-25
Favourites: ["Orange", "Red", "Blue"]

在这里,如果用户1搜索匹配率为33%或至少有一个共同匹配的用户,他们将只获得用户2.如果他们搜索了66%或至少两个常见匹配,他们将获得用户3。

我已经完成了简单的部分并按年龄范围进行了匹配,并尝试使用mongoDB $all$in,但这并不是我正在寻找的。有人能指出我正确的方向吗?

3 个答案:

答案 0 :(得分:1)

好吧,如果你想找到具有某些共同属性的对象,我会采取不同的方法。我将在属性上创建全文索引。在您的特定情况下,它是Favorites

搜索文本时,全文索引要快得多。它还会显示text score,显示给定术语在集合中的匹配程度。

在您的特定情况下,我会测量text score以查看其他文档是否符合我的标准。

您需要先创建full text索引。

db.collection.createIndex({"Favourites":"text"})

创建全文索引后,假设您尝试查找至少66%匹配的所有文档。这意味着如果我们有三个文本术语,我们希望所有文档至少匹配3个术语中的两个。

var match = 2;
var terms = "Red Green Blue";

db.collection.aggregate([
 { $match: { $text: { $search: terms } } },
 { $project: {User:1, _id:0, Name:1, "Age Range":1, Favourites:1, score: {$meta: "textScore"}}},
 { $sort: { score: 1 }},
 { $match: { score: { $gte: match } } }
])

在上面的示例中,我们希望找到至少包含两个匹配术语的所有文档。上面的代码段将返回:

{ 
    "User" : 3.0, 
    "Name" : "z", 
    "Age Range" : "19-25", 
    "Favourites" : [
        "Orange", 
        "Red", 
        "Blue"
    ], 
    "score" : 2.2
}
{ 
    "User" : 1.0, 
    "Name" : "x", 
    "Age Range" : "19-25", 
    "Favourites" : [
        "Red", 
        "Green", 
        "Blue"
    ], 
    "score" : 3.3000000000000003
}

我们找回了两个至少符合两个条款的文件。

<强>更新

OP提到术语可以包含多词短语。 MongoDB全文允许搜索短语,并要求用字符串引号包装短语。

e.g。 var terms = "Red \"Light Blue\"";

使用上面的代码段并提供该文档在收藏夹中包含Light Blue短语,将返回匹配的文档。

然而有一个问题。如果有的话,MongoDB总是对其他术语的短语执行logical and操作。在上面的示例中,代码将搜索包含词组Light Blue和词语Red

的文档

请参阅https://docs.mongodb.com/manual/reference/operator/query/text/#phrases

答案 1 :(得分:0)

This will help
你期望结果如此吗? 例如:搜索“收藏夹”至少两个常见匹配,['橙色','红色','粉红色']。因此“User3”是期望。查询如下:

db.test.aggregate([ 
{"$match": 
{ 
    favourites: {"$in" : ['orange','red', 'pink']}
 } 
},
 { "$unwind": "$favourites" },
{ "$match": { favourites: { "$in":  ['orange','red', 'pink'] } }},

{"$group" :
{
    "_id": {
        "_id": {"id":"$_id", "name":"$name"},
        "favourites": "$favourites"
    }
}
},
{ "$group": {
    "_id": "$_id._id",
    "favourites": { "$push": "$_id.favourites" },
    "length": { "$sum": 1 }
}},
{ "$match": { "length":  2  }}
])

结果:

{
"result" : [ 
    {
        "_id" : ObjectId("574cf11b0b3052089fe57605"),
        "favourites" : [ 
            "red", 
            "orange"
        ],
        "length" : 2
    }
],
"ok" : 1
}

答案 2 :(得分:0)

This博客提供了一个简单的建议,即只需创建一个查询,通过逐个列出所需的属性并为每个文档分配相似值并简单地将其添加为部分来组合每个文档的匹配的查询。 (这里的示例是从博客中删除的,但我确定您将能够为自己的数据结构修复它);

"$project" : {
  "c" : {"$add" : [
     {"$cond" : [{"$eq" : ["$firstname","John"]},1,0]},
     {"$cond" : [{"$eq" : ["$middleone","Andrew"]},1,0]},
     {"$cond" : [{"$eq" : ["$middletwo","Cartwright"]},1,0]},
     {"$cond" : [{"$eq" : ["$lastname","Smith"]},1,0]}
        ]
  }

您可以通过简单地获取搜索发起者列表并在查询中一次包含一个元素,为收藏夹数组扩展此内容。

这里的好处是您可以根据最相似的内容订购结果。