我想知道是否可以通过最接近的匹配来访问MongoDB中的文档。
例如我的搜索查询始终包含:
name
country
city
遵守规则:
1. name
始终必须匹配
2.如果存在country
或city
,则国家/地区的优先级更高
3.如果country
或city
不匹配,请仅考虑此文档,如果它们具有默认值(例如,对于字符串:"")
示例查询:
name
="测试"
country
=" USA"
city
="西雅图"
文件:
db.stuff.insert([
{
name:"Test",
country:"",
city:"Seattle"
},{
name:"Test3",
country:"USA",
city:"Seattle"
},{
name:"Test",
country:"USA",
city:""
},{
name:"Test",
country:"Germany",
city:"Seattle"
},{
name:"Test",
country:"USA",
city:"Washington"
}
])
它应该返回第3个文件
谢谢!
答案 0 :(得分:2)
考虑到不确定的要求和相互矛盾的更新,答案恰恰是一个解决问题的指导原则,它是否可行?"一部分。
应调整示例以满足期望。
db.stuff.aggregate([
{$match: {name: "Test"}}, // <== the fields that should always match
{$facet: {
matchedBoth: [
{$match: {country: "USA", city: "Seattle"}}, // <== bull's-eye
{$addFields: {weight: 10}} // <== 10 stones
],
matchedCity: [
{$match: {country: "", city: "Seattle"}}, // <== the $match may need to be improved, see below
{$addFields: {weight: 5}}
],
matchedCountry: [
{$match: {country: "USA", city: ""}},
{$addFields: {weight: 0}} // <== weightless, yet still a match
]
// add more rules here, if needed
}},
// get them together. Should list all rules from above
{$project: {doc: {$concatArrays: ["$matchedBoth", "$matchedCity", "$matchedCountry"]}}},
{$unwind: "$doc"}, // <== split them apart
{$sort: {"doc.weight": -1}}, // <== and order by weight, desc
// reshape to retrieve documents in its original format
{$project: {_id: "$doc._id", name: "$doc.name", country: "$doc.country", city: "$doc.city"}}
]);
问题中解释最少的部分会影响我们如何构建方面。 e.g。
{$match: {country: "", city: "Seattle"}}
匹配国家/地区明确存在且为空字符串的所有文档。
很可能
{$match: {country: {$ne: "USA"}, city: "Seattle"}}
获取所有具有匹配名称和城市以及任何国家/地区,甚至
的文档 {$match: {$and: [{$or: [{country: null}, {country: ""}]}, {city: "Seattle"}]}}
等
答案 1 :(得分:0)
这是一个查询
db.collection.aggregate([
{$match: {name:"Test"}},
{$project: {
name:"$name",
country: "$country",
city:"$city",
countryMatch: {$cond: [{$eq:["$country", "USA"]}, true, false]},
cityMatch: {$cond:[{$eq:["$city", "Seattle"]}, true, false]}
}},
{$match: {$and: [
{$or:[{countryMatch:true},{country:""}]},
{$or:[{cityMatch:true},{city:""}]}
]}},
{$sort: {countryMatch:-1, cityMatch:-1}},
{$project: {name:"$name", country:"$country", city:"$city"}}
])
说明:
首次匹配过滤掉与名称不匹配的文档(因为规则#1 - 名称应该匹配)。
下一个投影选择文档字段以及有关国家和城市匹配的一些信息。我们需要它来进一步过滤和排序文档。
第二场比赛过滤掉那些与国家和城市不匹配的文件,并且没有这些字段的默认值(规则#3)。
排序文档会在城市匹配之前移动国家/地区匹配,因为规则#2状态。最后 - 投影选择必填字段。
输出:
{
_id: 3,
name : "Test",
country : "USA",
city : ""
},
{
_id: 1,
name : "Test",
country : "",
city : "Seattle"
}
您可以限制查询结果以获得最接近的匹配。