あなたが範囲とは対照的に、不足しているバックすべての個別のIDを取得して受け入れることができる場合、これはあなたのクエリです:
collection.aggregate({
$group: {
"_id": null, // group all documents into the same bucket
"numbers":
{
$push: "$number" // create an array of all "number" fields
}
}
}, {
$project: {
"_id": 0, // get rid of the "_id" field - not really needed
"numbers": {
$setDifference: [ { // compute the difference between...
$range: [ 0, 10 ] // ... all numbers from 0 to 10 - adjust this to your needs...
}, "$numbers" ] // ...and the available values for "number"
}
}
})
あり、この情報のうち、範囲を計算する方法があるが、私は感じこれを持っていますあなたの場合には必要ないかもしれません。
ここでは、離散的な数値から範囲に到達するためのいくつかの段階を追加した、より長いバージョンです。コードは正確ではなく、おそらく超高速ではありませんが、少なくとも作業...
collection.aggregate({
$sort: {
"number": 1 // we need to sort in order to find ranges later
}
},
{
$group: {
"_id": null, // group all documents into the same bucket
"numbers":
{
$push: "$number" // create an array of all "number" fields
}
}
}, {
$project: {
"_id": 0, // get rid of the "_id" field - not really needed
"numbers": {
$setDifference: [ { // compute the difference between...
$range: [ 0, 10 ] // ... all numbers from 0 to 10 - adjust this to your needs...
}, "$numbers" ] // ...and the available values for "number"
}
}
},
{
$project: {
"numbers": "$numbers", // ...we create two identical arrays
"numbers2": "$numbers" // ...by duplicating our missing numbers array
}
},
{
$unwind: "$numbers" // this will flatten one of the two created number arrays
},
{
$project: {
"number": "$numbers",
"precedingNumber": {
$arrayElemAt: [
"$numbers2", // use the second (remaining) numbers array to find the previous number...
{ $max: [0, { $add: [ { $indexOfArray: [ "$numbers2", "$numbers" ] }, -1 ] } ] } // ...which needs to sit in that sorted array at the position of the element we're looking at right now - 1
]
},
"followingNumber": {
$arrayElemAt: [
"$numbers2", // use the second (remaining) numbers array to find the next number...
{ $add: [ { $indexOfArray: [ "$numbers2", "$numbers" ] }, 1 ] } // ...which needs to sit in that sorted array at the position of the element we're looking at right now + 1
]
}
}
}, {
$project: {
"number": 1, // include number
"precedingInRange": { $cond: [ { $eq: [ { $add: [ "$number", -1 ] }, "$precedingNumber" ] }, true, false ] },
"followingInRange": { $cond: [ { $eq: [ { $add: [ "$number", 1 ] }, "$followingNumber" ] }, true, false ] }
}
}, {
$match: {
$or: [ // filter out all items that are inside a range (or rather: include only the outer items of each range)
{ "precedingInRange": false },
{ "followingInRange": false }
]
}
}, {
$project: { // some beautification of the ouput to help deal with the data in your application
"singleNumber": { $cond: [ { $not: { $or: [ "$precedingInRange", "$followingInRange" ] } }, "$number", null ] },
"startOfRange": { $cond: [ "$followingInRange", "$number", null ] },
"endOfRange": { $cond: [ "$precedingInRange", "$number", null ] }
}
})
UPDATE 2:
:
私はきれいに関与あまり魔法なしの範囲を取得する方法のより良い方法を発見した感覚を持っています
collection.aggregate({
$sort: {
"number": 1 // we need to sort by numbers in order to be able to do the range magic later
}
}, {
$group: {
"_id": null, // group all documents into the same bucket
"numbers":
{
$push: "$number" // create an array of all "number" fields
}
}
}, {
$project: {
"numbers": {
$reduce: {
input: "$numbers",
initialValue: [],
in: {
"start": {
$concatArrays: [
"$$value.start",
{
$cond: { // if preceding element in array of numbers is not "current element - 1" then add it, otherwise skip
if: { $ne: [ { $add: [ "$$this", -1 ] }, { $arrayElemAt: [ "$numbers", { $add: [ { $indexOfArray: [ "$numbers", "$$this" ] }, -1 ] } ] } ] },
then: [ "$$this" ],
else: []
}
}
]
},
"end": {
$concatArrays: [
"$$value.end",
{
$cond: { // if following element in array of numbers is not "current element + 1" then add it, otherwise skip
if: { $ne: [ { $add: [ "$$this", 1 ] }, { $arrayElemAt: [ "$numbers", { $add: [ { $indexOfArray: [ "$numbers", "$$this" ] }, 1 ] } ] } ] },
then: [ "$$this" ],
else: []
}
}
]
}
}
}
}
}
}, {
$project: {
"ranges": {
$zip: {
inputs: [ "$numbers.start", "$numbers.end" ],
}
}
}
})
私はあなたの質問をよく理解していません。指定した範囲の存在数を照会しますか?または、指定した範囲の不足している数値を照会したいですか? – barbakini
技術的にどちらかがあります。主なことは、各ドキュメントのクエリを避け、ドキュメントが存在するかどうかを確認することです。代わりに、すでに存在する次の範囲または存在しない次の範囲のいずれかを返すクエリが1つ必要です。 –