如何在Mongodb中连接所有值并查找特定的子字符串?

如何在Mongodb中连接所有值并查找特定的子字符串?,mongodb,mapreduce,mongodb-query,aggregation-framework,Mongodb,Mapreduce,Mongodb Query,Aggregation Framework,我有这样的json文档: { “A”:[ { “C”:“abc”, “D”:“de” }, { “C”:“fg”, “D”:“嗨” } ] } 我将检查“A”是否包含字符串ef。 首先连接所有值abcdefghi,然后搜索ef 在XML中,XPATH类似于: //A[包含(,'ef')] Mongodb中是否有类似的查询?对于这种类型的搜索,所有选项都非常糟糕,但是您可以采取一些方法。请注意,虽然这里的最终案例可能是最好的解决方案,但为了说明问题,我提供了一些选项 如果数组“A”中的键定义一致

我有这样的json文档:

{
“A”:[
{
“C”:“abc”,
“D”:“de”
},
{
“C”:“fg”,
“D”:“嗨”
}
]
}
我将检查“A”是否包含字符串ef。 首先连接所有值abcdefghi,然后搜索ef

在XML中,XPATH类似于:
//A[包含(,'ef')]


Mongodb中是否有类似的查询?

对于这种类型的搜索,所有选项都非常糟糕,但是您可以采取一些方法。请注意,虽然这里的最终案例可能是最好的解决方案,但为了说明问题,我提供了一些选项

如果数组“A”中的键定义一致,并且始终包含一个数组,则搜索方式如下:

db.collection.aggregate([
//筛选包含零件的文档
{“$match”:{
“$and”:[
{“$or”:[
{“A.C”:/e/},
{“A.D”:/e/}
]},
{“$or”:[
{“A.C”:/f/},
{“A.D”:/f/}
]}
]
}},
//保留原始表单和数组的副本
{“$project”:{
“_id”:{
“\u id”:“$\u id”,
“A”:“$A”
},
“A”:1
}},
//展开阵列
{“$unwind”:“$A”},
//将两个字段合并并推送到单个数组
{“$组”:{
“\u id”:“$\u id”,
“已加入”:{“$push”:{
“$concat”:[“$A.C”,“$A.D”]
}}
}},
//复制数组
{“$project”:{
“C”:“$已加入”,
“D”:“$JOINTED”
}},
//展开两个阵列
{“$unwind”:“$C”},
{“$unwind”:“$D”},
//加入副本并测试它们是否相同
{“$project”:{
“已加入”:{“$concat”:[“$C”、“$D”]},
“相同”:{“$eq”:[“$C”、“$D”]},
}},
//放弃“相同”元素并搜索所需字符串
{“$match”:{
“相同”:错误,
“已加入”:{“$regex”:“ef”}
}},
//投影匹配文档的原始形式
{“$project”:{
“\u id”:“$\u id.\u id”,
“A”:“$\u id.A”
}}
])
因此,除了可怕的
$regex
匹配之外,还有一些困难需要解决,以便将字段“连接”起来,以便再次按顺序搜索字符串。还要注意,此处可能出现的反向连接可能会产生假阳性。目前,没有简单的方法来避免反向连接或以其他方式对其进行过滤,因此需要考虑。

另一种方法是基本上通过任意JavaScript运行所有内容。mapReduce方法可用于此目的。在这里,您可以对“a”中包含的数据类型稍微宽松一点,并尝试结合一些更具条件的匹配,以尝试减少正在处理的文档集:

db.collection.mapReduce(
函数(){
var=”;
if(Object.prototype.toString.call(this.A)='[Object Array]'){
this.A.forEach(函数(doc){
for(单据中的var k){
合并+=单据[k];
}
});
}否则{
joined=this.A;//假定这只是一个字符串
}
var id=这个;
删除此[“_id”];
if(joined.match(/ef/))
发射(id,this);
},
函数(){},//将不会减少
{ 
“查询”:{
“$or”:[
{“A”:/ef/},
{“$and”:[
{“$or”:[
{“A.C”:/e/},
{“A.D”:/e/}
]},
{“$or”:[
{“A.C”:/f/},
{“A.D”:/f/}
]}
] }
]
},
“out”:{“inline”:1}
}
);
因此,您可以使用任意逻辑来搜索包含的对象。这一个只是区分“数组”和假定一个字符串,允许查询的附加部分首先搜索匹配的“字符串”元素,这是一个“短路”求值

但实际上,在一天结束时,最好的方法是将数据存在文档中,并且在更新文档内容时,您必须自己维护这些数据:

{
“A”:[
{
“C”:“abc”,
“D”:“de”
},
{
“C”:“fg”,
“D”:“嗨”
}
],
“搜索”:“abcdefghi”
}
因此,这仍然会调用一个可怕的使用
$regex
类型查询的方法,但至少这可以避免(或者说转向编写文档)为实现对所需字符串的搜索而“连接”元素的开销

最终的结果是,一个“全面”的文本搜索解决方案,也就是说,与MongoDB中的文本搜索功能不同,此时的外部解决方案可能是您最佳的性能选择

在创建“连接”字段时使用“预存储”方法,或者在受支持的其他情况下(Solr是一个可以做到这一点的解决方案),在为文档内容编制索引时创建的文本索引中有一个“计算字段”

无论如何,这些都是解决问题的方法和要点。这不是XPath搜索,也不是他们对整个集合的某种“类似XPath”的视图(从这个意义上讲),因此,您最适合按照将为您提供最佳性能的方法构建数据

尽管如此,这里的示例是一个相当做作的示例,如果您有一个“类似”这样的实际用例,那么这个实际用例可能会成为一个非常有趣的问题。实际情况一般有不同的解释