在 Mongo 中存储查询

dex*_*ter 6 mongodb

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

我有一个产品集合,我想根据多个参数进行查询。在这里可以找到其中的一些:

产品内:

"delivery" : {
    "maximum_delivery_days" : 30,
    "average_delivery_days" : 10,
    "source" : 1,
    "filling_rate" : 85,
    "stock" : 0
}
Run Code Online (Sandbox Code Playgroud)

但也存在其他参数。

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

"$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
                                            }
                                    }
                            ]
                    }
            ]
        }
]
Run Code Online (Sandbox Code Playgroud)

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

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

{ 
    "name": "query1",
    "query": { the thing printed above starting with "$or"... }
}
Run Code Online (Sandbox Code Playgroud)

使用:

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

结果是:

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
Run Code Online (Sandbox Code Playgroud)

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

但是当我尝试更新“查询”中的值时,更改不会发生。绝不。甚至有时也不行。但是,我可以创建一个新对象并丢弃前一个对象。所以,解决方法就在那里。

db.queries.update(
    {"name": "query1"},
    {"$set": { 
            ... update goes here ...
        }
    }
)
Run Code Online (Sandbox Code Playgroud)

这样做会导致:

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

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

不得不说,我对这里发生的事情一无所知,所以我希望这里的一些巫师能够对此事有所了解

Lix*_*Lix 1

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

QUERY 错误:字段名称不能以 $ 开头

由于您尝试在文档中存储查询(或查询的一部分),因此您最终会得到包含 mongo 运算符关键字(例如$or, $ne, $gt)的属性名称。mongo 文档实际上引用了这个确切的场景- 添加了重点

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


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

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