Mongo / Node:按单个属性过滤吗?

时间:2019-03-02 22:48:52

标签: node.js mongodb

我正在处理一个带有criteria对象的查询,该对象将作为该查询的第一个参数传递:

module.exports = (criteria, sortProperty, offset = 0, limit = 20) => {
  // write a query that will follow sort, offset, limit options only
  // do not worry about criteria yet
  console.log(criteria);

  const query = Artist.find({ age: { $gte: 19, $lte: 44 } })
    .sort({ [sortProperty]: 1 })
    .skip(offset)
    .limit(limit);

  return Promise.all([query, Artist.count]).then(results => {
    return {
      all: results[0],
      count: results[1],
      offset: offset,
      limit: limit
    };
  });
};

默认情况下,criteria对象只有一个name属性,它是一个空字符串。

age属性指向同时分配了minmax值的对象。我在yearsActive对象的内部还有一个criteria属性,并且还具有一个minmax值。

所以有三个不同的属性:agenameyearsActive

这对我来说是一个极具挑战性的挑战,如果您看的远,那是我所能达到的。

在我的criteria属性被控制台记录时,它只有一个名称{ name: "" }。首次启动时,默认情况下没有yearsActiveage。这样便是滑块的作用所在。当我开始在前端移动这些滑块时,它会将ageyearsActive附加到criteria对象上。

因此,我需要弄清楚如何更新查询以考虑例如不同的年龄,并且我一直在考虑在辅助函数内使用if条件。

2 个答案:

答案 0 :(得分:1)

关于我留下的评论。

将数据检索到UI时,您至少具有三种状态。在这种情况下,我建议您使用聚合以将数据作为模型检索为您的业务。

例如,您遇到的问题是,有时您不知道 age yearsActive 的最大值或最小值,但是您也应该可能是 ObjectId 的标识符,该标识符将用于更新由该属性标识的模型。

Artist.aggregate([
{
    $match: { age: { $gte: 19, $lte: 44 } }
},
{
    $sort: { yourProperty: 1 }
},
{
    $skip: 10
},
{
    $limit: 10
},
{
    $project: {
        // You set your properties to retrieve with the 1 as flag
        propertieX: 1,
        "another.property": 1,
        "age.max": {
            $cond: {
                if: { $eq: [ "", "$age.max" ] },
                then: 0, // Or the value that you want to set it
                else: "$age.max"
            }
        }
    }
}]);

另一种状态是当您根据从表单提交的参数进行查询时。

如果您保证使用所需的逻辑检索模型。例如,您应该在每个请求中使用 $ project 返回此模型,并在不存在前端操作的情况下应用默认值,因为在搜索中应该易于管理。

{
    ObjectId: YOUR_OBJECT_ID,
    age: {
        min: YOUR_MIN_VALUE,
        max: YOUR_MAX_VALUE
    },
    yearsActive: {
        min: YOUR_MIN_VALUE,
        max: YOUR_MAX_VALUE
    }
}

最后,当您发送数据进行保存时,应该发送返回的整个模型,但必须要注意的是,通过 ObjectId 仅标识该元素以进行更新。

注意根据我从您的问题中了解到的信息,我会采用这种方法,如果我对我的解释不好,请告诉我,如果您想要共享更多信息或打开存储库以用代码理解,应该更容易让我理解该问题

答案 1 :(得分:0)

所以我决定这样做是因为创建所有单独的Artist.find({})代码看起来很混乱,是创建一个单独的辅助函数:

const buildQuery = (criteria) => {
    console.log(criteria);
};

此辅助函数正在与criteria对象一起调用,我必须以这种方式构成对象,使其以我要搜索Artist集合的方式表示查询。

这使我难以理解的原因是,结构不完善的对象用于搜索具有随机属性的集合,例如age,其最小值和最大值是Mongo不知道如何处理的默认情况下。 MongoDB不知道min和max到底是什么意思。

因此,在帮助器函数中,我从此函数中为return创建了一个单独的对象,该对象将代表我想发送给Mongo的实际query

const buildQuery = (criteria) => {
    console.log(criteria);
    const query = {};
};

我无论如何都没有修改该对象,我只是从该UI对象中读取一些所需的搜索结果或用户希望看到的内容,因此我将该对象命名为query,并添加了这个想法的age

const buildQuery = (criteria) => {
    console.log(criteria);
    const query = {};
    query.age = {};
};

我决定针对想要查找的特定年龄范围在辅助函数中进行if有条件的操作。

const buildQuery = (criteria) => {
    console.log(criteria);
    const query = {};
    if (criteria.age) {
        query.age = {};
    }
};

因此,这就是Mongo查询运算符发挥作用的地方。我要考虑的两个运算符是大于或等于($gte)和小于或等于($lte)个运算符。

这是我在实践中实际实现的方式:

const buildQuery = (criteria) => {
    console.log(criteria);
    const query = {};
    if (criteria.age) {
        query.age = {
            $gte: criteria.age.min,
            $lte: criteria.age.max
        };
    }
};

此处的query对象最终将从buildQuery函数返回:

const buildQuery = (criteria) => {
    console.log(criteria);
    const query = {};
    if (criteria.age) {
        query.age = {
            $gte: criteria.age.min,
            $lte: criteria.age.max
        };
    }
    return query;
};

query对象将传递给查找操作:

module.exports = (criteria, sortProperty, offset = 0, limit = 20) => {
  // write a query that will follow sort, offset, limit options only
  // do not worry about criteria yet

  const query = Artist.find(buildQuery(criteria))
    .sort({ [sortProperty]: 1 })
    .skip(offset)
    .limit(limit);

  return Promise.all([query, Artist.count]).then(results => {
    return {
      all: results[0],
      count: results[1],
      offset: offset,
      limit: limit
    };
  });
};

const buildQuery = (criteria) => {
    console.log(criteria);
    const query = {};
    if (criteria.age) {
        query.age = {
            $gte: criteria.age.min,
            $lte: criteria.age.max
        };
    }
    return query;
};

所以我在这里要做的就是获得Artist.find({ age: { $gte: minAge, $lte: maxAge })的等价物。

所以对于yearsActive,我决定实现几乎相同的东西:

const buildQuery = criteria => {
  console.log(criteria);
  const query = {};
  if (criteria.age) {
    query.age = {
      $gte: criteria.age.min,
      $lte: criteria.age.max
    };
  }

  if (criteria.yearsActive) {

  }

  return query;
};

因此,如果用户更改了滑块,我将期望我的条件对象具有在其上定义的YearsActive属性,如下所示:

const buildQuery = criteria => {
  console.log(criteria);
  const query = {};
  if (criteria.age) {
    query.age = {
      $gte: criteria.age.min,
      $lte: criteria.age.max
    };
  }

  if (criteria.yearsActive) {
    query.yearsActive = {
       $gte: criteria.yearsActive.min,
       $lte: criteria.yearsActive.max
     }
  }

  return query;
};