首页 > 解决方案 > Mongodb 聚合失败:“FieldPath 字段名称可能不以'$'开头。”

问题描述

我试图弄清楚为什么这段代码会失败:

db.restaurants.drop();

db.restaurants.insertMany( [
  { "_id" : 1, "borough" : "Manhattan"},
] );

db.restaurants.createIndex({
  "borough": "text"
})

db.restaurants.aggregate([
  { $match: { $text: { $search: "a" } } },
  { $sort: {score: {"$meta": "textScore"}}},
  { $project: {"_id": true}},
])

错误输出:

uncaught exception: Error: command failed: {
        "ok" : 0,
        "errmsg" : "FieldPath field names may not start with '$'.",
        "code" : 16410,
        "codeName" : "Location16410"
} : aggregate failed :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:18:14
_assertCommandWorked@src/mongo/shell/assert.js:639:17
assert.commandWorked@src/mongo/shell/assert.js:729:16
DB.prototype._runAggregate@src/mongo/shell/db.js:266:5
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1058:12
@(shell):1:1

我知道这与项目声明有关...

先感谢您!

-丹尼尔

标签: mongodbaggregation-framework

解决方案


您的问题几乎类似于这个Mongodb 4.4.0 FieldPath 字段名称可能不是以开头,我已经回答了解决方案,唯一的区别是投影字段和一些用例!

经过大量研究,我在“投影”部分下的查找和聚合函数text-score-metadata-meta-textscore的一般条款中找到了以下说明,

{ $meta: "textScore" }表达式可以是投影文档的一部分以包括文本分数元数据。

$meta表达式可以出现在包含或排除投影中。

如果将表达式设置为文档中已存在的字段名称,则投影的元数据值将覆盖现有值。

上面的粗体语句清除,如果您使用$projectstage after $sortstage scoreor text index字段borough应该是包含或排除

根据您的尝试解决方案:

db.restaurants.aggregate([
  { $match: { $text: { $search: "a" } } },
  { $sort: { score: { "$meta": "textScore" } } },
  { 
    $project: {
      "_id": true, // or _id: 1
      "borough": false // or borough: 0
    }
  },
  // or by default _id would be included
  /*
  { 
    $project: {
      "borough": false // or borough: 0
    }
  },
  */
  // or below will work but this will work as exclusion projection, so you need to specify your other fields to exclude,
  /* 
  { 
    $project: {
      "_id": true, // or _id: 1
      "score": false, // or score: 0
    }
  }
  */
  // or by default _id would be included
  /*
  { 
    $project: {
      "score": false, // or score: 0
    }
  },
])

还有其他方法,我推荐这种方法

  • 交换$project$sort舞台,
db.restaurants.aggregate([
  { $match: { $text: { $search: "a" } } },
  { $project: { "_id": true } },
  { $sort: { score: { "$meta": "textScore" } } }
])

推荐阅读