Mongo PHP Получение длины массива (больше или меньше) [дубликат]

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

486
задан styvane 11 June 2016 в 05:06
поделиться

10 ответов

Обновление:

Для версий mongodb 2.2+ более эффективный способ сделать это, описанный @JohnnyHK в другом ответе .

< hr>

1.Использование $, где

db.accommodations.find( { $where: "this.name.length > 1" } );

Но ...

Javascript выполняется медленнее, чем исходные операторы, перечисленные на этой странице, но очень гибкая. См. Страницу обработки на стороне сервера для получения дополнительной информации.

2.Создайте дополнительное поле NamesArrayLength, обновите его длиной массива имен и затем используйте в запросах:

db.accommodations.find({"NamesArrayLength": {$gt: 1} });

Это будет лучшее решение и будет работать намного быстрее (вы можете создать на нем индекс).

368
ответ дан Community 26 August 2018 в 04:28
поделиться

Попробуйте сделать что-то вроде этого:

db.getCollection('collectionName').find({'ArrayName.1': {$exists: true}})

1 - это номер, если вы хотите получить запись больше 50, а затем ArrayName.50 Спасибо.

26
ответ дан Aman Goel 26 August 2018 в 04:28
поделиться

Вы также можете использовать агрегат:

db.accommodations.aggregate(
[
     {$project: {_id:1, name:1, zipcode:1, 
                 size_of_name: {$size: "$name"}
                }
     },
     {$match: {"size_of_name": {$gt: 1}}}
])

// вы добавляете «size_of_name» для переноса документа и используете его для фильтрации размера имени

39
ответ дан arun 26 August 2018 в 04:28
поделиться

Я нашел это решение, чтобы найти элементы с полем массива, большим определенной длины

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"
9
ответ дан Barrard 26 August 2018 в 04:28
поделиться

Более эффективный способ сделать это в MongoDB 2.2+ теперь можно использовать числовые индексы массива в ключах объектов запроса.

// Find all docs that have at least a second name array element.
db.accommodations.find({'name.1': {$exists: true}})
1038
ответ дан JohnnyHK 26 August 2018 в 04:28
поделиться

Хотя приведенные выше ответы на все работают, то, что вы изначально пытались сделать, было правильным способом, однако у вас есть только синтаксис назад (переключатель «$ size» и «$ gt»).

Исправить :

db.collection.find({items: {$gt: {$size: 1}}})

Неверно:

db.collection.find({items: {$size: {$gt: 1}}})
-5
ответ дан Steffan Perry 26 August 2018 в 04:28
поделиться

Я считаю, что это самый быстрый запрос, который отвечает на ваш вопрос, потому что он не использует интерпретированное предложение $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" ] }
>
109
ответ дан Tobia 26 August 2018 в 04:28
поделиться

Вы можете использовать $ expr (оператор версии 3.6 mongo) для использования функций агрегации в регулярном запросе.

Сравнить query operators vs aggregation comparison operators .

db.accommodations.find({$expr:{$gt:[{$size:"$name"}, 1]}})
7
ответ дан Veeram 26 August 2018 в 04:28
поделиться
db.accommodations.find({"name":{"$exists":true, "$ne":[], "$not":{"$size":1}}})
15
ответ дан Yadvendar 26 August 2018 в 04:28
поделиться

Ничто из этого не помогло мне. Я сделал это:

db.collection.find( {arrayName : {$exists:true}, $where:'this.arrayName.length>1'} )
30
ответ дан Zloy Smiertniy 26 August 2018 в 04:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: