Неизвестный оператор верхнего уровня MongoDB $ gte [duplicate]

Это описывает распространенную ошибку с использованием замыканий в JavaScript.

Функция определяет новую среду

. Рассмотрим:

function makeCounter()
{
  var obj = {counter: 0};
  return {
    inc: function(){obj.counter ++;},
    get: function(){return obj.counter;}
  };
}

counter1 = makeCounter();
counter2 = makeCounter();

counter1.inc();

alert(counter1.get()); // returns 1
alert(counter2.get()); // returns 0

Для каждого времени makeCounter, {counter: 0} приводит к созданию нового объекта. Кроме того, создается новая копия obj для ссылки на новый объект. Таким образом, counter1 и counter2 не зависят друг от друга.

Замыкания в циклах

Использование замыкания в цикле является сложным.

Рассмотрим:

var counters = [];

function makeCounters(num)
{
  for (var i = 0; i < num; i++)
  {
    var obj = {counter: 0};
    counters[i] = {
      inc: function(){obj.counter++;},
      get: function(){return obj.counter;}
    }; 
  }
}

makeCounters(2);

counters[0].inc();

alert(counters[0].get()); // returns 1
alert(counters[1].get()); // returns 1

Обратите внимание, что counters[0] и counters[1] независимы не . Фактически, они работают на одном и том же obj!

Это связано с тем, что есть только одна копия obj, разделенная на все итерации цикла, возможно, по соображениям производительности. Несмотря на то, что {counter: 0} создает новый объект на каждой итерации, одна и та же копия obj будет просто обновляться с ссылкой на самый новый объект.

Решение состоит в использовании другой вспомогательной функции:

function makeHelper(obj)
{
  return {
    inc: function(){obj.counter++;},
    get: function(){return obj.counter;}
  }; 
}

function makeCounters(num)
{
  for (var i = 0; i < num; i++)
  {
    var obj = {counter: 0};
    counters[i] = makeHelper(obj);
  }
}

Это работает, потому что локальные переменные в области функции напрямую, а также переменные аргументов функции выделяются новыми экземплярами при записи.

Подробное обсуждение см. в JavaScript ловушки закрытия и использование

485
задан 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} });

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

367
ответ дан Community 21 August 2018 в 15:40
поделиться

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

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

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

26
ответ дан Aman Goel 21 August 2018 в 15:40
поделиться

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

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 21 August 2018 в 15:40
поделиться

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

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 21 August 2018 в 15:40
поделиться

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

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

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

Исправить :

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

Неверно:

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

Я считаю, что это самый быстрый запрос, который отвечает на ваш вопрос, потому что он не использует интерпретированное предложение $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 21 August 2018 в 15:40
поделиться

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

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

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

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

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

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