【问题标题】:$where mongo operator work around in meteorjs$where mongodb 运算符在流星 js 中工作
【发布时间】:2014-06-25 16:36:33
【问题描述】:

我有一个在 MongoDB shell 中完美运行的 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 中实现这一点,解决方法是什么?

根据要求的解释: 我需要一个服务器端的功能,不管它是否在客户端工作。 该函数必须将给定数组与文档上的数字字段匹配,并告诉我数组中有多少数字匹配以及文档 ID 或类似的东西:

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

试过这个: 在(meteor is server)中添加代码:

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 shell 中可以完美运行。

解决方案感谢@AndrewMao: 第一种解决方案: 通过在函数末尾添加 .toString() ,我测试的 .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();

第二个解决方案:如果您想在查询中添加自定义数组或其他内容:

您必须在一行中将函数作为字符串传递,也可以像我对随机数组所做的那样在其中添加其他字符串。看看下面例子中的函数调用(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();

【问题讨论】:

  • 问问自己是否真的需要这么复杂。您需要消除该功能。也许还可以在问题中指定您需要此构造的目的。
  • @marcodejongh 我认为意图很明确。这是一个“乐透”抽奖评估,如从给定集合中匹配的 7 个数字。有几种方法可以处理这个问题,只是它们都超出了“minimongo”的范围。为此,我希望流星用户能够理解客户端实现的局限性,而只需使用服务器端代码。整个集合端匹配对客户端没有意义。
  • @NeilLunn 那么你会如何做这个服务器端呢?据我所知,meteor 中的服务器端 find 接受与客户端 mini mongo 变体相同的选择器。所以你仍然无法使用函数。我能想到的唯一方法是使用 npm 模块手动连接到流星。
  • @MarcodeJongh 我根据您的要求编辑了问题添加说明。
  • 你的代码失败了吗?按照 Meteor 的约定,您将首先定义一个集合,该集合只能是服务器端的,例如Numbers = new Meteor.Collection('numbers')。然后 Meteor 代码中的服务器端 Numbers.find() 将对应于 mongo shell 中的 db.numbers.find() 。从那里您可以诊断 $where 是否失败。

标签: mongodb meteor


【解决方案1】:

您的问题可能与$where 查询无关;这是因为您打印的是光标而不是匹配的文档。即在.find()的末尾追加.fetch()http://docs.meteor.com/#fetch

光标是对选定文档组的引用,在您尝试对其进行.map().fetch().forEach() 之前,它实际上不会抓取这些文档。

此外,您需要将$where 函数作为字符串传递,而不是作为实际函数传递:https://groups.google.com/forum/#!topic/meteor-talk/ErgCC4g_bB0。这是 Mongo 处理和运行函数所必需的(它不在 Node 中完成。)

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

您将无法享受源代码突出显示的好处,但您测试的功能应该可以工作。你也可以试试

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

但这可能只适用于浏览器而不适用于 Node。

【讨论】:

  • 当我执行 .fetch() 时,集合中的所有文档都将打印出来。
  • 那是因为你有它在一个 console.log() 块。你期望会发生什么? Meteor 的集合 API 不是 MongoDB shell 命令的精确副本,您不应该期望它具有相同的语法。
  • 我希望它会像在 mondodb shell 中一样工作,只会打印出匹配的文档
  • 是的,这就是为什么我在标题中说明了解决方法!
  • 将函数作为字符串传入。在答案中查看我的更新。
猜你喜欢
  • 2021-03-10
  • 2022-01-12
  • 1970-01-01
  • 1970-01-01
  • 2022-07-06
  • 1970-01-01
  • 1970-01-01
  • 2014-10-31
  • 2015-12-23
相关资源
最近更新 更多