我有一个用例,我需要输入一些属性列表,这些属性列表在mongodb中提供结果搜索,其中90%属性与所有数据匹配。 例如: 我有像
这样的数据[{
id: 1,
properties: {
'property1': 'value1',
'property2': 'value2',
'property3': 'value3',
'property4': 'value4',
'property5': 'value5'
}
},
{
id: 2,
properties: {
'property1': 'value1',
'property2': 'value2',
'property6': 'value6',
'property7': 'value7',
'property8': 'value8',
'property9': 'value9'
}
},
{
id: 3,
properties: {
'property9': 'value9'
}
}]
我想搜索几个属性,我正在寻找至少50%的匹配,至少1个属性应该匹配任何两个输入 输入查询
find
{
'property3', 'value3',
'property7', 'value7'
}
从上面的输入中,它与DB中的3个数据中的2个数据匹配。 可以用MongoDB写查询吗?
答案 0 :(得分:1)
这是应该让你去的东西(你需要一个更新版本的MongoDB,但至少是v3.4.4):
db.collection.aggregate({
$addFields: { // we add a helper field
"propertiesAsArray": { // called "propertiesAsArray"
$objectToArray: "$properties" // which will be the array representation of the "properties" field
}
}
}, {
$addFields: {
"matchRatio": { // the value we are looking for is...
$divide: [ { // ...the ratio between...
$size: { // ...the number of items...
$filter: {
"input": "$propertiesAsArray", // ...in our magic property array...
"as": "this",
"cond": { // ...that match any of our conditions...
$or: [
{ $eq: [ "$$this", { "k": "property3", "v": "value3" } ] },
{ $eq: [ "$$this", { "k": "property7", "v": "value7" } ] },
// ...of which we could have any number...
]
}
}
}
}, 2 ] // ...and the number of properties in your query
}
}
}, {
$facet: { // create two separate stages
"totalNumberOfDocs": [{
$count: "count" // one just calculates the total number of documents
}],
matchingDocs: [{ // and the second stage first filters out the non-matching documents
$match: {
"matchRatio": { $gte: 0.50 } // we only want documents with a match ratio >= 50%
}
}, {
$count: "count" // and then counts the remaining ones
}]
}
}, {
$project: { // final calculation of the ratio ("2 out of 3" in your example --> 66%)
"percentage": {
$divide: [
{ $arrayElemAt: [ "$matchingDocs.count", 0 ] },
{ $arrayElemAt: [ "$totalNumberOfDocs.count", 0 ] }
]
}
}
})
如果你只是在寻找匹配的文件并且不太关心66%的数字那么这应该有用(未经测试,因为我正在路上)。
db.collection.aggregate({
$addFields: { // we add a helper field
"propertiesAsArray": { // called "propertiesAsArray"
$objectToArray: "$properties" // which will be the array representation of the "properties" field
}
}
}, {
$addFields: {
"matchRatio": { // the value we are looking for is...
$divide: [ { // ...the ratio between...
$size: { // ...the number of items...
$filter: {
"input": "$propertiesAsArray", // ...in our magic property array...
"as": "this",
"cond": { // ...that match any of our conditions...
$or: [
{ $eq: [ "$$this", { "k": "property3", "v": "value3" } ] },
{ $eq: [ "$$this", { "k": "property7", "v": "value7" } ] },
// ...of which we could have any number...
]
}
}
}
}, 2 ] // ...and the number of properties in your query
}
}
}, {
$match: {
"matchRatio": { $gte: 0.50 } // we only want documents with a match ratio >= 50%
}
})