在Mongo

时间:2016-03-27 13:17:14

标签: mongodb

就是这种情况:我想在其中根据一组参数配置应在sjop中列出哪些项目的网上商店。 我希望这是可配置的,因为这允许我尝试不同的参数也很容易改变它们的值。

我有一个我想根据多个参数查询的Product集合。 其中有几个在这里找到:

产品中的

"delivery" : {
    "maximum_delivery_days" : 30,
    "average_delivery_days" : 10,
    "source" : 1,
    "filling_rate" : 85,
    "stock" : 0
}

但也存在其他参数。

决定是否包含产品的此类查询的示例可以是:

"$or" : [
        {
            "delivery.stock" : 1
        },
        {
            "$or" : [
                    {
                            "$and" : [
                                    {
                                            "delivery.maximum_delivery_days" : {
                                                    "$lt" : 60
                                            }
                                    },
                                    {
                                            "delivery.filling_rate" : {
                                                    "$gt" : 90
                                            }
                                    }
                            ]
                    },
                    {
                            "$and" : [
                                    {
                                            "delivery.maximum_delivery_days" : {
                                                    "$lt" : 40
                                            }
                                    },
                                    {
                                            "delivery.filling_rate" : {
                                                    "$gt" : 80
                                            }
                                    }
                            ]
                    },
                    {
                            "$and" : [
                                    {
                                            "delivery.delivery_days" : {
                                                    "$lt" : 25
                                            }
                                    },
                                    {
                                            "delivery.filling_rate" : {
                                                    "$gt" : 70
                                            }
                                    }
                            ]
                    }
            ]
        }
]

现在要使这个可配置,我需要能够处理布尔逻辑,参数和值。 所以,我有了这个想法,因为这样的查询本身就是JSON,将它存储在Mongo中并让我的Java应用程序检索它。 接下来就是在过滤器中使用它(例如查找或其他)并处理相应的产品选择。 这种方法的优点是我可以在程序之外实际分析数据和查询的有效性。

我会在数据库中按名称存储它。例如。

{ 
    "name": "query1",
    "query": { the thing printed above starting with "$or"... }
}

使用:

db.queries.insert({
    "name" : "query1",
    "query": { the thing printed above starting with "$or"... }
})

结果是:

2016-03-27T14:43:37.265+0200 E QUERY    Error: field names cannot start with $ [$or]
    at Error (<anonymous>)
    at DBCollection._validateForStorage (src/mongo/shell/collection.js:161:19)
    at DBCollection._validateForStorage (src/mongo/shell/collection.js:165:18)
    at insert (src/mongo/shell/bulk_api.js:646:20)
    at DBCollection.insert (src/mongo/shell/collection.js:243:18)
    at (shell):1:12 at src/mongo/shell/collection.js:161

但我可以使用Robomongo存储它,但并非总是如此。显然我做错了什么。但我没有想法它是什么。 如果它失败了,我创建了一个全新的集合并再试一次,它就会成功。奇怪的东西超出了我能理解的范围。

但是当我尝试更新&#34;查询&#34;中的值时,更改不会进行。决不。有时甚至都没有。 然而,我可以创建一个新对象并丢弃前一个对象。所以,解决方法就在那里。

db.queries.update(
    {"name": "query1"},
    {"$set": { 
            ... update goes here ...
        }
    }
)

这样做会导致:

WriteResult({
        "nMatched" : 0,
        "nUpserted" : 0,
        "nModified" : 0,
        "writeError" : {
                "code" : 52,
                "errmsg" : "The dollar ($) prefixed field '$or' in 'action.$or' is not valid for storage."
        }
})

似乎非常接近上面的其他消息。

有人说,我对这里发生的事情一无所知,所以我希望这里的一些w w能够解决这个问题

4 个答案:

答案 0 :(得分:1)

我认为错误消息包含您需要考虑的重要信息:

  

QUERY错误:字段名称无法以$

开头

由于您尝试在文档中存储查询(或其中一部分),因此最终会得到包含mongo运算符关键字的属性名称(例如$or$ne,{ {1}})。 The mongo documentation actually references this exact scenario - 强调添加

  

字段名称不能包含点(即。)或空字符,它们不能以美元符号开头(即$) ......

在这些情况下,我不相信像Robomongo这样的第三方应用程序。我建议直接在mongo shell中调试/测试这个问题。

我的建议是在您的文档中存储转义版本的查询,以免干扰保留的运算符关键字。您可以使用可用的$gt将部分查询编码为字符串,然后在您选择稍后检索时对其进行解析/解码:JSON.stringify(my_obj);

答案 1 :(得分:1)

您在MongoDB中将查询存储为JSON对象的方法是不可行的。

您可能会在MongoDB中存储查询逻辑和字段,但您必须使用适当的MongoDB语法构建查询的外部应用程序。

MongoDB查询包含运算符,其中一些运算符中包含特殊字符。

有mongoDB文件名的规则。这些规则不允许使用特殊字符。 看这里:https://docs.mongodb.org/manual/reference/limits/#Restrictions-on-Field-Names

您有时可以使用Robomongo成功创建文档的可能原因是因为Robomongo正在将您的查询转换为字符串并在将特殊字符发送到MongoDB时正确转义它。

这也解释了为什么你更新它们的尝试永远不会起作用。您尝试创建文档,但创建了一个字符串对象,因此您的更新条件可能不会检索任何文档。

答案 2 :(得分:0)

我发现你的方法存在两个问题。

在以下查询中

db.queries.insert({
   "name" : "query1",
   "query": { the thing printed above starting with "$or"... }
})

有效的JSON需要键值对。在"query"中,您存储的对象没有key。你有两个选择。将查询存储为文本或在花括号内创建另一个键。

第二个问题是,您存储query值而不用引号括起来。所有字符串值必须用引号括起来。

所以你的最终文件应该显示为

db.queries.insert({
    "name" : "query1",
    "query": 'the thing printed above starting with "$or"... '
})

现在试试,它应该有用。

答案 3 :(得分:0)

显然,我尝试以mongo的方式存储查询的方式是愚蠢的,因为@bigdatakid和@lix的答案都清楚了。所以我最终做的是:我改变了字段的命名以符合mongo要求。

E.g。而不是$或我使用_ $等等而不是使用。我用的名字里面是#。我在Java代码中替换了这两个。

这样我仍然可以轻松地尝试在我的程序之外测试查询。在我的Java程序中,我只需更改名称并使用查询。仅使用2行代码。它现在很有效。谢谢你们提出的建议。

String documentAsString = query.toJson().replaceAll("_\\$", "\\$").replaceAll("#", ".");
    Object q = JSON.parse(documentAsString);