$ где оператор монго обходится в meteorjs

#mongodb #meteor

#mongodb #метеор

Вопрос:

У меня есть запрос MongoDB, который отлично работает в оболочке MongoDB

  db.collection.find({ $where: 
function(){
    var num = this.numbers;
    function isInList(numbers,matchArray) 
        {
            var reducedNums = numbers.filter(function(num) {
            return matchArray.indexOf(num) !== -1
            });
            if (reducedNums.length == 7){
                return true;
            } else {
                return false;
            }
        }
    return isInList(num, [ 28 ,5, 17, 47, 1, 24, 37, 19, 4, 3 ] );
    }
}
);
 

Как я могу реализовать это в MeteorJS, что такое обходной путь?

Пояснения по запросу: Мне нужна функция на стороне сервера, не имеет значения, работает ли она на стороне клиента. Функция должна сопоставить данный массив с полем чисел в документе и сообщить мне, сколько чисел в массиве совпадают, и идентификатор документа или что-то вроде этого :

 if (match.length == 7){
                return "DOCUMENT";
            } else {
                return false;
            }
 

Пробовал это:
Добавлен код в (meteor является сервером):

 console.log(Tickets.find({ $where: 
function(){
        var num = this.numbers;
        function isInList(numbers,matchArray) 
            {
                var reducedNums = numbers.filter(function(num) {
                return matchArray.indexOf(num) !== -1
                });
                if (reducedNums.length == 7){
                    return true;
                } else {
                    return false;
                }
            }
        return isInList(num, [ 28 ,5, 17, 47, 1, 24, 37, 19, 4, 3 ] );
        }
    }
))
 

вывод был таким:

  I20140623-17:15:02.690(2)? { _mongo:
 I20140623-17:15:02.910(2)?    { _connectCallbacks: [ [Function] ],
 I20140623-17:15:02.911(2)?      _observeMultiplexers: {},
 I20140623-17:15:02.912(2)?      _onFailoverHook: { nextCallbackId: 0, callbacks: {} },
 I20140623-17:15:02.913(2)?      _docFetcher: { _mongoConnection: [Circular], _callbacksForCacheKey: {} },
 I20140623-17:15:02.914(2)?      _oplogHandle:
 ...
 ...
 ...
 I20140623-17:15:03.025(2)?      selector: { '$where': [Function] },
 I20140623-17:15:03.027(2)?      options: { transform: null } },
 I20140623-17:15:03.030(2)?   _synchronousCursor: null }
 => Meteor server restarted
 

Когда я это делаю.fetch() все документы будут распечатаны, чего не должно произойти, этот код отлично работает в оболочке mondodb.

Решение спасибо @AndrewMao: 1-е решение: путем добавления .toString() в конце функции the .toString(), как я тестировал, отлично работает в NodeJS

пример:

 Tickets.find({'$where':     function(){
    var num = this.numbers;
    function isInList(numbers,matchArray) 
        {
            var reducedNums = numbers.filter(function(num) {
            return matchArray.indexOf(num) !== -1
            });
            if (reducedNums.length == 7){
                return true;
            } else {
                return false;
            }
        }
    return isInList(num, [ 28 ,5, 17, 47, 1, 24, 37, 19, 4, 3 ] );
    }.toString();
}).fetch();
 

2-е решение: это если вы хотите добавить свой пользовательский массив или что-то еще в запрос:

Вы должны передать свою функцию в виде строки в одной строке, также вы можете добавить в нее другую строку, как я сделал со случайным массивом. Посмотрите на вызов функции (isInList(num,[‘ random ‘]);}’) в примере ниже.

пример:

  var random = [ 19 ,3, 14, 24, 2, 38, 48, 19, 4, 3 ];

 Tickets.find({'$where': 'function(){var num = this.numbers; function isInList(numbers,matchArray) {var reducedNums = numbers.filter(function(num) { return matchArray.indexOf(num) !== -1  }); if (reducedNums.length == 7){ return true;} else {  return false;   }}return isInList(num,['  random  ']);}'}).fetch();
 

Комментарии:

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

2. @marcodejongh Я думаю, что намерение довольно ясно. Это оценка розыгрыша «лото», как в случае совпадения 7 чисел из заданного набора. Есть несколько способов обработать это, просто все они выходят за рамки «minimongo». Для чего я хотел бы, чтобы пользователи meteor понимали ограничения реализации на стороне клиента и просто переходили к коду на стороне сервера. Сопоставление всей коллекции на стороне клиента не имеет смысла.

3. @NeilLunn Как бы вы тогда сделали это на стороне сервера? Насколько я знаю, серверная функция поиска в meteor принимает те же селекторы, что и клиентская версия mini mongo. Таким образом, вы все равно не сможете использовать функцию. Единственный способ, который я мог придумать, — это вручную подключиться к meteor с помощью модуля npm.

4. @MarcodeJongh Я отредактировал вопрос, добавив объяснение в соответствии с вашим запросом.

5. Ваш код не работает? По соглашению в Meteor вы начнете с определения коллекции, которая может быть только на стороне сервера, например, Numbers = new Meteor . Коллекция (‘numbers’). Тогда Numbers.find() на стороне сервера в вашем коде Meteor будет соответствовать db.numbers.find() в оболочке mongo. Оттуда вы можете диагностировать, не работает ли $where или нет.

Ответ №1:

Вероятно, ваша проблема не в $where запросе; это потому, что вы печатаете курсор, а не соответствующие документы. А именно, добавьте .fetch() в конец .find() : http://docs.meteor.com/#fetch

Курсор является ссылкой на выбранную группу документов и фактически не захватывает документы, пока вы не попытаетесь .map() , .fetch() , или .forEach() на нем.

Кроме того, вам нужно передать $where функцию как строку, а не как фактическую функцию: https://groups.google.com/forum /#!тема/метеоритный разговор/ErgCC4g_bB0. Это необходимо для того, чтобы Mongo обрабатывал и запускал функцию (это не выполняется в Node).)

 Tickets.find({ $where: 'function() { ... }' });
 

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

 Tickets.find({ $where: function() { ... }.toString() });
 

но это может работать только в браузерах, а не в узле.

Комментарии:

1. Когда я это делаю. fetch() все документы в коллекции распечатываются.

2. Это потому, что у вас это есть в console.log() блоке. Что вы ожидали, что произойдет? API сбора данных Meteor не является точной копией команд оболочки MongoDB, и вы не должны ожидать, что он будет иметь тот же синтаксис.

3. Я ожидаю, что он будет работать как в оболочке mondodb, которая будет распечатывать только те документы, которые соответствуют

4. Да, именно поэтому я указал в названии, что такое обходной путь!!

5. Передайте функцию в виде строки. Смотрите Мое обновление в ответе.