我的收藏:
{
title: 'Computers',
maincategories:[
{
title: 'Monitors',
subcategories:[
{
title: '24 inch',
code: 'AFG'
}
]
}
]
}
我想查询代码。代码只是第一部分,所以我想拥有包含给定搜索的所有子类别。所以AFG101
将返回此子类别。
我的查询:
module.exports = (req, res) => {
var q = {
'maincategories.subcategories': {
$elemMatch: {
code: 'AFG101'
}
}
};
var query = mongoose.model('TypeCategory').find(q, {'maincategories.$': 1, 'title': 1});
query.exec((err, docs) => {
res.status(200).send(docs);
});
};
我的问题:
如何搜索字符串的一部分? AFG101
应返回包含字符串任何部分的属性code
的所有子类别。所以在这种情况下,AFG
会很受欢迎。与此sql问题相同:MySQL: What is a reverse version of LIKE?
如何投影子类别。当前查询返回所有子类别。我只想回报那些击球。
答案 0 :(得分:1)
执行此操作的最佳方法是使用$indexOfCP
字符串聚合运算符在MongoDB 3.4中。
let code = "afg101";
db.collection.aggregate([
{ "$project": {
"title": 1,
"maincategories": {
"$map": {
"input": "$maincategories",
"as": "mc",
"in": {
"$filter": {
"input": "$$mc.subcategories",
"as": "subcat",
"cond": {
"$gt": [
{
"$indexOfCP": [
code,
{ "$toLower": "$$subcat.code" }
]
},
-1
]
}
}
}
}
}
}}
])
返回:
{
"_id" : ObjectId("582cba57e6f570d40d77b3a8"),
"title" : "Computers",
"maincategories" : [
[
{
"title" : "24 inch",
"code" : "AFG"
}
]
]
}
从3.2向后,唯一的方法是使用mapReduce
。
db.collection.mapReduce(
function() {
var code = 'AFG101';
var maincategories = this.maincategories.map(function(sdoc) {
return {
"title": sdoc.title,
"subcategories": sdoc.subcategories.filter(function(scat) {
return code.indexOf(scat.code) != -1;
}
)};
});
emit(this._id, maincategories);
},
function(key, value) {},
{ "out": { "inline": 1 }
})
产生类似这样的东西:
{
"results" : [
{
"_id" : ObjectId("582c9a1aa358615b6352c45a"),
"value" : [
{
"title" : "Monitors",
"subcategories" : [
{
"title" : "24 inch",
"code" : "AFG"
}
]
}
]
}
],
"timeMillis" : 15,
"counts" : {
"input" : 1,
"emit" : 1,
"reduce" : 0,
"output" : 1
},
"ok" : 1
}
答案 1 :(得分:0)
好吧,就像你的问题有两个部分一样,我可以想到两个独立的解决方案,但我没有看到将它们连接在一起的方法。
对于第一部分$ where可用于执行反向正则表达式,但它很脏,它是一个过度杀手而且它不能使用任何索引,因为$ where运行在每个文档上。
db.TypeCategory.find({$where:function(){for(var i in this.maincategories)
{for(var j in this.maincategories[i].subcategories)
{if("AFG101".indexOf(this.maincategories[i].subcategories[j].code)>=0)
{return true}}}}},{"maincategories.subcategories.code":1})
即使使用此选项,也需要进行几次边界检查,并且无法投影两级嵌套数组。 MongoDB不支持此类投影。
为此目的,我们可能会进行聚合
db.TypeCategory.aggregate([{$unwind:"$maincategories"},
{$unwind:"$maincategories.subcategories"},
{$match:{"maincategories.subcategories.code":"AFG"}},
{$group:{_id:"$_id","maincategories":{$push:"$maincategories"}}}
])
但是我不认为有一种方法可以在聚合中进行反向正则表达式检查,但我也可能错了。此聚合也是昂贵的,因为有两个unwinds可能导致溢出内存限制以便为真正大的集合进行聚合。
答案 2 :(得分:0)
您可以使用$ substr并执行此操作
db.getCollection('cat').aggregate([
{"$unwind" : "$maincategories"},
{"$unwind" : "$maincategories.subcategories"},
{"$project" :
{"maincategories" : 1,
"title":1,"sub" : {"$substr" :["$maincategories.subcategories.code",0,3]}}},
{"$match" : {"sub" : "AFG"}},
{"$project" :
{"maincategories" : 1,
"title":1}
}
])