Wygląda na to, że twoje pytanie wyraźnie dotyczyło „zdobądź co n-ty przypadek”, co wydaje się być całkiem jasnym pytaniem.
Operacje zapytań, takie jak .find()
może naprawdę zwrócić dokument "tak jak jest" z wyjątkiem ogólnego pola "wybór" w projekcji i operatorów, takich jak pozycyjny $
operator dopasowania lub $elemMatch
które pozwalają na pojedynczy dopasowany element tablicy.
Oczywiście istnieje $slice
, ale to tylko pozwala na "wybór zakresu" w tablicy, więc znowu nie ma zastosowania.
"Jedyne" rzeczy, które mogą modyfikować wynik na serwerze to .aggregate()
i .mapReduce()
. Ten pierwszy w żaden sposób nie „gra bardzo dobrze” z „cięciem” tablic, przynajmniej nie przez „n” elementów. Jednak ponieważ argumenty "function()" mapReduce są oparte na logice JavaScript, masz trochę więcej miejsca do zabawy.
W procesach analitycznych i do celów analitycznych „tylko” wystarczy filtrować zawartość tablicy za pomocą mapReduce przy użyciu .filter()
:
db.collection.mapReduce(
function() {
var id = this._id;
delete this._id;
// filter the content of "instances" to every 3rd item only
this.instances = this.instances.filter(function(el,idx) {
return ((idx+1) % 3) == 0;
});
emit(id,this);
},
function() {},
{ "out": { "inline": 1 } } // or output to collection as required
)
W tym momencie jest to tak naprawdę tylko „biegacz JavaScript”, ale jeśli jest to tylko do analizy/testowania, to ogólnie nie ma nic złego w tej koncepcji. Oczywiście dane wyjściowe nie są „dokładnie” zbudowane tak, jak twój dokument, ale są one tak bliskie, jak tylko mapReduce.
Inna sugestia, którą tu widzę, wymaga utworzenia nowej kolekcji ze wszystkimi elementami „zdenormalizowanymi” i wstawienia „indeksu” z tablicy jako części unikalnego _id
klucz. Może to dać coś, co można bezpośrednio zapytać, ale dla „każdego n-tego elementu” nadal musiałbyś zrobić:
db.resultCollection.find({
"_id.index": { "$in": [2,5,8,11,14] } // and so on ....
})
Więc wypracuj i podaj wartość indeksu „co n-tego elementu”, aby uzyskać „co n-ty element”. Więc to naprawdę nie rozwiązuje problemu, o który pytano.
Jeśli formularz wyjściowy wydawałby się bardziej pożądany do celów „testowych”, lepszym kolejnym zapytaniem dotyczącym tych wyników byłoby użycie potoku agregacji z $redact
db.newCollection([
{ "$redact": {
"$cond": {
"if": {
"$eq": [
{ "$mod": [ { "$add": [ "$_id.index", 1] }, 3 ] },
0 ]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
To przynajmniej używa "warunku logicznego" podobnego do tego, który został zastosowany w .filter()
wcześniej, aby po prostu wybrać pozycje "n-tego indeksu" bez wymieniania wszystkich możliwych wartości indeksu jako argumentu zapytania.