MongoDB索引边界约束

MongoDB索引边界约束,mongodb,indexing,Mongodb,Indexing,在我接触MongoDB的过程中,我开始了解MongoDB索引的一个问题。问题是MongoDB索引有时不强制执行查询的两端边界。以下是我在查询数据库时遇到的一个输出: 查询: db.user.find({transaction:{$elemMatch:{product:"mobile", firstTransaction:{$gte:ISODate("2015-01-01"), $lt:ISODate("2015-01-02")}}}}).hint("transaction.product_1_t

在我接触MongoDB的过程中,我开始了解MongoDB索引的一个问题。问题是MongoDB索引有时不强制执行查询的两端边界。以下是我在查询数据库时遇到的一个输出:

查询:

db.user.find({transaction:{$elemMatch:{product:"mobile", firstTransaction:{$gte:ISODate("2015-01-01"), $lt:ISODate("2015-01-02")}}}}).hint("transaction.product_1_transaction.firstTransaction_1").explain()
db.user.find({transaction:{$elemMatch:{product:'mobile'}}}).min({transaction:{$elemMatch:{firstTransaction:ISODate("2015-01-01")}}}).max({transaction:{$elemMatch:{firstTransaction:ISODate("2015-01-02")}}})
输出:

"cursor" : "BtreeCursor transaction.firstTransaction_1_transaction.product_1",
                            "isMultiKey" : true,
                            "n" : 622,
                            "nscannedObjects" : 350931,
                            "nscanned" : 6188185,
                            "nscannedObjectsAllPlans" : 350931,
                            "nscannedAllPlans" : 6188185,
                            "scanAndOrder" : false,
                            "indexOnly" : false,
                            "nYields" : 235851,
                            "nChunkSkips" : 0,
                            "millis" : 407579,
                            "indexBounds" : {
                                    "transaction.firstTransaction" : [
                                            [
                                                    true,
                                                    ISODate("2015-01-02T00:00:00Z")
                                            ]
                                    ],
                                    "transaction.product" : [
                                            [
                                                    "mobile",
                                                    "mobile"
                                            ]
                                    ]
                            },
planner returned error: unable to find relevant index for max/min query
正如您在上面的firstTransaction字段示例中看到的,绑定的一端是true,而不是我提到的日期。我发现这个解决方法是min(),max()函数。我尝试了这些方法,但它们似乎不适用于嵌入式文档(transaction是一个包含firstTransaction、product等字段的子文档数组)。我发现以下错误:

查询:

db.user.find({transaction:{$elemMatch:{product:"mobile", firstTransaction:{$gte:ISODate("2015-01-01"), $lt:ISODate("2015-01-02")}}}}).hint("transaction.product_1_transaction.firstTransaction_1").explain()
db.user.find({transaction:{$elemMatch:{product:'mobile'}}}).min({transaction:{$elemMatch:{firstTransaction:ISODate("2015-01-01")}}}).max({transaction:{$elemMatch:{firstTransaction:ISODate("2015-01-02")}}})
输出:

"cursor" : "BtreeCursor transaction.firstTransaction_1_transaction.product_1",
                            "isMultiKey" : true,
                            "n" : 622,
                            "nscannedObjects" : 350931,
                            "nscanned" : 6188185,
                            "nscannedObjectsAllPlans" : 350931,
                            "nscannedAllPlans" : 6188185,
                            "scanAndOrder" : false,
                            "indexOnly" : false,
                            "nYields" : 235851,
                            "nChunkSkips" : 0,
                            "millis" : 407579,
                            "indexBounds" : {
                                    "transaction.firstTransaction" : [
                                            [
                                                    true,
                                                    ISODate("2015-01-02T00:00:00Z")
                                            ]
                                    ],
                                    "transaction.product" : [
                                            [
                                                    "mobile",
                                                    "mobile"
                                            ]
                                    ]
                            },
planner returned error: unable to find relevant index for max/min query
firstTransaction字段以及product和它们的复合索引也被索引。我不知道这里出了什么问题

样本文件:

{
_id: UUID (indexed by default),
name: string,
dob: ISODate,
addr: string,
createdAt: ISODate (indexed),
.
.
.,
transaction:[
{
firstTransaction: ISODate(indexed),
lastTransaction: ISODate(indexed),
amount: float,
product: string (indexed),
.
.
.
},...
],
other sub documents...
}

这是正确的行为。您不能总是与
$lte
$gte
的索引边界相交-有时它会给出不正确的结果。例如,考虑文件

{ "x" : [{ "a" : [4, 6] }] }
此文档与查询匹配

db.test.find({ "x" : { "$elemMatch" : { "a" : { "$gte" : 5, "$lte" : 5 } } } });
如果我们在
{“x.a”:1}
上定义一个索引,那么两个索引边界将是
[5,无穷]
,和
[-infinity,5]
。将它们相交将得到
[5,5]
,并且使用此索引边界将与文档不匹配-错误


您能否提供一个示例文档,并告诉我们有关您试图对查询执行的操作的更多信息?有了上下文,可能还有另一种编写使用更严格索引边界的查询的方法。

查看您的查询,而不仅仅是
explain
的输出,这将非常有帮助……我明白您的意思了。虽然我的field-firstTransaction不是整个集合中的数组&但我想限制在两个索引端,以便限制对文档的搜索以获得性能。我希望给定的示例文档能有所帮助。示例显示索引边界行为涉及数组,但问题是MongoDB不强制字段的类型,因此任何字段都可以有数组值。因此,即使仅当嵌入文档中存在数组字段时,我们才被禁止与索引边界相交,但通常情况下,我们仍然被禁止与边界相交。另外,您能否描述一下查询的目的,即它试图为您的应用程序实现什么,以及示例文档?您将无法实现您可能认为应该应用于当前形式的查询的“完美”索引边界。好吧,我试图做的是获取特定产品在特定持续时间内发生的第一次事务数。示例文档如我在问题中所解释的。你需要我用数据来解释吗?我想建立一个报告,比如谁在12月14日完成了产品“mobile”的第一笔交易。