【问题标题】:Lack of rich querying functionality in NoSQL?NoSQL 中缺乏丰富的查询功能?
【发布时间】:2015-04-30 19:29:18
【问题描述】:

每次我考虑使用 NoSQL 作为解决方案时,我总是对缺乏丰富的查询功能感到困惑。我认为这很可能是我对 NoSQL 缺乏了解。这也可能是因为我对 SQL 非常熟悉。据我了解,NoSQL 确实非常适合简单的模式场景(因此它可能不适用于拥有 50 多个表的关系数据库)。即使对于琐碎的场景,我似乎总是想要丰富的查询功能。让我们以食谱数据库为例。

虽然该方案无疑是微不足道的,但您肯定需要丰富的查询能力。您可能希望通过以下(以及更多)搜索:

  • 标题
  • 标签
  • 类别
  • 身份证
  • 喜欢
  • 创建食谱的用户
  • 创建日期
  • 评分
  • 饮食限制

您还希望将这些条件组合成您想要的任何组合。虽然我知道大多数 NoSQL 解决方案都有二级索引,但这种类型的查询能力是否严重限制了 NoSQL 与多少解决方案相关?我通常需要这种丰富的查询能力。另一个很好的例子是错误跟踪应用程序。

我不认为您每次想要搜索数据库时都想启动 map reduce 工作(我认为这类似于大多数时间在传统关系模型中进行表扫描)。所以我假设会有很多查询,你必须遍历每个实体并寻找你想要搜索的标准(这可能会很慢)。我知道您可以每晚运行 map reduce 作业来分析数据或将其规范化为典型的关系数据库结构以用于报告。

现在我可以看到它对于您很可能总是必须读取所有数据的场景很有用。想想网络服务器日志或物联网类型的应用程序,您可以在其中收集大量数据(如审查收集)并进行夜间分析。

那么,对 NoSQL 的理解是否存在问题,或者我可以很好地处理的场景数量是否存在限制?

【问题讨论】:

  • nosql 数据库不仅仅是为了拥有一个数据库。这是为了有目的地存储东西。 noSQL 的全部好处是使查询更容易。阅读胜过写作。这意味着,如果您难以查询,您的设计可能很糟糕。
  • @cdbajorin 我认为您的评论并没有真正解决这个问题。它如何使它更容易?如果你擅长 sql 查询是很容易的。对于我给出的示例,查询将是微不足道的。即使它是“EASIER”并不意味着它“Fast”。在上面的示例中,用户很可能会混合并匹配条件以按他们想要的任何组合进行搜索。如果每秒执行 1000 次这样的查询,如何对你来说“设计”它要快。很可能每个查询都需要你接触每个文档,如果你有千兆/兆字节的数据,性能就会提高。

标签: database nosql


【解决方案1】:

我认为您遇到的问题是您使用与使用 SQL 相同的设计思维方式接近 noSQL。您多次提到“富查询”。对我来说,这指向设计缺陷(仅使用参考 ID/尝试定义关系)。 noSQL 中的一个重要概念是数据可以重复(并且通常应该重复)。您的配方示例实际上是 noSQL 的一个很好的用例。以下是我使用您提到的 3 个模型的方法(为简单起见):

Recipe = {
    _id: a001,
    name: "Burger",
    ingredients: [
        {
            _id: b001,
            name: "Beef"
        },
        {
            _id: b002,
            name: "Cheese"
        }
    ],
    createdBy: {
        _id: c001,
        firstName: "John",
        lastName: "Doe"
    }
}

Person = {
    _id: c001,
    firstName: "John",
    lastName: "Doe",
    email: "jd@email.com",
    preferences: {
        emailNotifactions: true
    }
}

Ingredient = {
    _id: b001,
    name: "Beef",
    brand: "Agri-co",
    shelfLife: "3 days",
    calories: 300
};

我以这种方式设计它的原因明确是为了它的存在(假设它类似于 allrecipes.com)。搜索/过滤食谱时,您可以按作者过滤,但他们的电子邮件偏好无关紧要。同样,成分的保质期和品牌也无关紧要。该模式是为特定用例设计的,不仅仅是因为您的数据需要保存。现在这里有一些你提到的查询(mongo):

db.recipes.find({name: "Burger"});
db.recipes.find({ingredients: { $nin: ["Cheese", "Milk"]}}) // dietary restrictions

您的丰富查询问题现在已减少为单个集合中的单个查询。

这种设计的缺点是写入速度较慢。您需要在后端有更多的逻辑,这可能会导致更多的程序员错误。由于访问各种模型以获取相关信息,因此写入速度也比 SQL 慢。话虽如此,它的查看频率与编写/编辑的频率是多少? (这是我对阅读胜过写作的评论)另一个主要缺点是远见的必要性。成分和配方之间的关系不会改变形式。但是您的应用程序需要的信息可能会。编辑 noSQL 模型往往比编辑 SQL 表更困难。

这是另一个人为设计的示例,使用相同的模型来强调我关于有目的的设计的观点。假设您的新网站是关于著名厨师而不是食谱数据库:

Person = {
    _id: c001,
    firstName: "Paula",
    lastName: "Deen",
    recipeCount: 15,
    commonIngredients: [
        {
            _id: b001,
            name: "Butter",
            count: 15
        },
        {
            _id: b002,
            name: "Salted Butter",
            count: 15
        }
    ],
    favoriteRecipes: [
        {
            _id: a001,
            name: "Fried Butter",
            calories: "3000"
        }
    ]
};

Recipe = {
    _id: a001,
    name: "Fried Butter",
    ingredients: [
        {
            _id: b001,
            name: "Butter"
        }
    ],
    directions: "Fry butter. Eat.",
    calories: "3000",
    rating: 99,
    createdBy: {
        _id: c001,
        firstName: "Paula",
        lastName: "Deen"
    }
};

Ingredient = {
    _id: b001,
    name: "Butter",
    brand: "Butterfields",
    shelfLife: "1 month"
};

这两种设计都使用相同的信息,但它们的建模是出于您费心收集信息的特定原因。现在,您拥有了厨师列表页面和典型排序/过滤的必要信息。您可以从那里导航到食谱页面并获得该信息。

为用例设计,而不是为关系建模。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-19
    • 1970-01-01
    • 1970-01-01
    • 2021-03-09
    • 1970-01-01
    • 2020-10-30
    • 1970-01-01
    相关资源
    最近更新 更多