Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb 从mongoose中的类似嵌套字段列表中选择相同字段_Mongodb_Mongoose_Mongoose Schema - Fatal编程技术网

Mongodb 从mongoose中的类似嵌套字段列表中选择相同字段

Mongodb 从mongoose中的类似嵌套字段列表中选择相同字段,mongodb,mongoose,mongoose-schema,Mongodb,Mongoose,Mongoose Schema,我有一个模式 const placeSchema = new Schema({ description: { fr: String, en: String, }, comment: { fr: String, en: String, }, ... ... }); const Place= mongoose.model('Place', placeSchema); module.exports =

我有一个模式

const placeSchema = new Schema({
    description: {
      fr: String,
      en: String,
    },
    comment: {
      fr: String,
      en: String,
    },
    ...
    ...
});

const Place= mongoose.model('Place', placeSchema);

module.exports = Place;
如果我只想获得我当前使用的“en”值

wait Place.find({},'-description.fr-comment.fr…)


如果相似字段的数量增加,查询的长度也会增加。有没有一种方法可以选择所有类似的字段,比如$field.fr?

技术上是的,有一种方法。使用并执行一些结构操作

它看起来像这样:

db.collection.aggregate([
  {
    $match: {} //match your document.
  },
  {
    $addFields: {
      rootArr: {
        $objectToArray: "$$ROOT"
      }
    }
  },
  {
    $unwind: "$rootArr"
  },
  {
    $match: {
      "rootArr.v.en": {
        $exists: true
      }
    }
  },
  {
    $group: {
      _id: "$_id",
      data: {
        $push: {
          k: "$rootArr.k",
          v: "$rootArr.v.en"
        }
      }
    }
  },
  {
    $replaceRoot: {
      newRoot: {
        $arrayToObject: "$data"
      }
    }
  }
])

这是一个有点“黑客”的想法,你的模式需求有多严格? 您是否考虑过在以下结构下建造它

const placeSchema = new Schema({
    data: [
        {
            lang: String,
            description: String,
            comment: String,
            ...
        }
    ]
});

以下聚合将检查子字段的所有顶级字段
en
。如果是truthy(如果您严格使用语言属性的字符串值,则应该可以使用),则子字段将是
{field:{en:fieldValue.en}}
,否则它将是
{field:fieldValue}

db.collection.aggregate([
  {
    $replaceRoot: {
      newRoot: {
        $arrayToObject: {
          $map: {
            input: { $objectToArray: "$$ROOT" },
            in: {
              k: "$$this.k",
              v: {
                $cond: [
                  "$$this.v.en", // works for string values, otherwise you will have to check more explicitly
                  {
                    en: "$$this.v.en"
                  },
                  "$$this.v"
                ]
              }
            }
          }
        }
      }
    }
  }
])

以上两个答案正是问题想要的。这可能是一种更“黑客”的做事方式

首先创建一个函数,生成查询字符串
'-description.fr-comment.fr…'

let select = '';
const selectLanguage = (fields, lang) => {
   switch (true) {
        case lang === 'fr':
            fields.forEach(field => {
                select= `${select} -${field}.en `;
            });
            break;
        case lang === 'en':
            fields.forEach(field => {
                select = `${select} -${field}.fr `;
            });
            break;
        default: 
            break;
    }
    
    return select;
}
这将生成一个字符串,如英语为
'-fieldName1.fr-fieldName2.fr..
,法语为
'-fieldName1.en..
。然后我们可以在上面的查询中使用这个语句

const select = selectLanguage(['description', 'comment', ..], 'en')

await Place.find({}, select)   //await Place.find({}, ' -description.fr -comment.fr ..')

我将切换到这个模式,因为它看起来更好,对我来说更有效。但是,如果我希望所有数据的评级都相同,那么嵌套字段(比如:
impression:{备注:String,rating:Number}
)会有问题吗?最终,你会最清楚如何使用数据,你应该试着找到让生活更轻松的最佳结构。数组中的嵌套字段有时会很麻烦,但Mongo提供了许多工具来处理它们。例如,[arrayFilters][使更新这些阵列变得非常容易。