#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. Передайте функцию в виде строки. Смотрите Мое обновление в ответе.