COUNTER PRIMITIVE
Давайте определим функции обратного вызова следующим образом:
// ****************************
// COUNTER BEING A PRIMITIVE
// ****************************
function test1() {
for (var i=0; i<2; i++) {
setTimeout(function() {
console.log(i);
});
}
}
test1();
// 2
// 2
По завершении таймаута он будет печатать 2 для обоих. Это связано с тем, что функция обратного вызова обращается к значению, основанному на лексической области , где была определена функция.
Чтобы передать и сохранить значение при определении обратного вызова, мы можем создать замыкание , чтобы сохранить значение до вызова обратного вызова. Это можно сделать следующим образом:
function test2() {
function sendRequest(i) {
setTimeout(function() {
console.log(i);
});
}
for (var i = 0; i < 2; i++) {
sendRequest(i);
}
}
test2();
// 1
// 2
Теперь в этом особенность: «Примитивы передаются по значению и копируются. Таким образом, когда ограничение определено, они сохраняют значение из предыдущего цикла».
COUNTER BEING OBJECT
Поскольку у закрытий есть доступ к родительским переменным функции через ссылку, этот подход будет отличаться от такового для примитивов.
// ****************************
// COUNTER BEING AN OBJECT
// ****************************
function test3() {
var index = { i: 0 };
for (index.i=0; index.i<2; index.i++) {
setTimeout(function() {
console.log('test3: ' + index.i);
});
}
}
test3();
// 2
// 2
Итак, даже если для переменной, передаваемой как объект, создается замыкание, значение индекса цикла не будет сохранено. Это означает, что значения объекта не копируются, а к ним обращаются через ссылку.
function test4() {
var index = { i: 0 };
function sendRequest(index, i) {
setTimeout(function() {
console.log('index: ' + index);
console.log('i: ' + i);
console.log(index[i]);
});
}
for (index.i=0; index.i<2; index.i++) {
sendRequest(index, index.i);
}
}
test4();
// index: { i: 2}
// 0
// undefined
// index: { i: 2}
// 1
// undefined
Обновление:
Для версий mongodb 2.2+ более эффективный способ сделать это, описанный @JohnnyHK в другом ответе .
< hr>1.Использование $, где
db.accommodations.find( { $where: "this.name.length > 1" } );
Но ...
Javascript выполняется медленнее, чем исходные операторы, перечисленные на этой странице, но очень гибкая. См. Страницу обработки на стороне сервера для получения дополнительной информации.
blockquote>2.Создайте дополнительное поле
NamesArrayLength
, обновите его длиной массива имен и затем используйте в запросах:db.accommodations.find({"NamesArrayLength": {$gt: 1} });
Это будет лучшее решение и будет работать намного быстрее (вы можете создать на нем индекс).
Попробуйте сделать что-то вроде этого:
db.getCollection('collectionName').find({'ArrayName.1': {$exists: true}})
1 - это номер, если вы хотите получить запись больше 50, а затем ArrayName.50 Спасибо.
Вы также можете использовать агрегат:
db.accommodations.aggregate(
[
{$project: {_id:1, name:1, zipcode:1,
size_of_name: {$size: "$name"}
}
},
{$match: {"size_of_name": {$gt: 1}}}
])
// вы добавляете «size_of_name» для переноса документа и используете его для фильтрации размера имени
Я нашел это решение, чтобы найти элементы с полем массива, большим определенной длины
db.allusers.aggregate([
{$match:{username:{$exists:true}}},
{$project: { count: { $size:"$locations.lat" }}},
{$match:{count:{$gt:20}}}
])
. Первый агрегат $ match использует аргумент, который истинен для всех документов. Если пусто, я получаю
"errmsg" : "exception: The argument to $size must be an Array, but was of type: EOO"
Более эффективный способ сделать это в MongoDB 2.2+ теперь можно использовать числовые индексы массива в ключах объектов запроса.
// Find all docs that have at least a second name array element.
db.accommodations.find({'name.1': {$exists: true}})
Хотя приведенные выше ответы на все работают, то, что вы изначально пытались сделать, было правильным способом, однако у вас есть только синтаксис назад (переключатель «$ size» и «$ gt»).
Исправить :
db.collection.find({items: {$gt: {$size: 1}}})
Неверно:
db.collection.find({items: {$size: {$gt: 1}}})
Я считаю, что это самый быстрый запрос, который отвечает на ваш вопрос, потому что он не использует интерпретированное предложение $where
:
{$nor: [
{name: {$exists: false}},
{name: {$size: 0}},
{name: {$size: 1}}
]}
Это означает «все документы, кроме тех, которые не имеют имени (либо несуществующий или пустой массив) или только с одним именем. "
Тест:
> db.test.save({})
> db.test.save({name: []})
> db.test.save({name: ['George']})
> db.test.save({name: ['George', 'Raymond']})
> db.test.save({name: ['George', 'Raymond', 'Richard']})
> db.test.save({name: ['George', 'Raymond', 'Richard', 'Martin']})
> db.test.find({$nor: [{name: {$exists: false}}, {name: {$size: 0}}, {name: {$size: 1}}]})
{ "_id" : ObjectId("511907e3fb13145a3d2e225b"), "name" : [ "George", "Raymond" ] }
{ "_id" : ObjectId("511907e3fb13145a3d2e225c"), "name" : [ "George", "Raymond", "Richard" ] }
{ "_id" : ObjectId("511907e3fb13145a3d2e225d"), "name" : [ "George", "Raymond", "Richard", "Martin" ] }
>
Вы можете использовать $ expr (оператор версии 3.6 mongo) для использования функций агрегации в регулярном запросе.
Сравнить query operators
vs aggregation comparison operators
.
db.accommodations.find({$expr:{$gt:[{$size:"$name"}, 1]}})
db.accommodations.find({"name":{"$exists":true, "$ne":[], "$not":{"$size":1}}})
Ничто из этого не помогло мне. Я сделал это:
db.collection.find( {arrayName : {$exists:true}, $where:'this.arrayName.length>1'} )