【问题标题】:Send mongodb aggregation criteria through url query string通过url查询字符串发送mongodb聚合条件
【发布时间】:2019-02-21 04:38:18
【问题描述】:

我想要实现的是在客户端构建一个 MongoDB 聚合阶段,然后通过 URL 查询字符串将其发送到 Web API 以获取基于这些条件的结果。

我正在使用这个网址与邮递员进行调试:

http://.../monsters/aggregate?pipes={"$match":{"name":"foo"}, "$max": 2}

在我的控制器中:

    [HttpGet("aggregate")]
    public async Task<IActionResult> GetByAggregate([FromQuery(Name = "pipes")]string pipes)
    {
        if (!string.IsNullOrEmpty(pipes))
        {
            BsonDocument d = BsonDocument.Parse(pipes);

            var p = PipelineDefinition<T, T>.Create(d);

            IAsyncCursor<T> result = await _monsterService.AggregateAsync(p);

            return Ok(result.ToListAsync());
        }

        return NotFound();
    }

这不起作用,错误消息:

MongoCommandException:命令聚合失败:管道阶段规范对象必须只包含一个字段..

但是有了这个网址,我得到了我想要的:

http://.../monsters/aggregate?pipes={"$match":{"name":"foo"}}

如何将mongodb管道解析为url查询字符串的正确json格式,然后反序列化到api端的mongodb管道阶段?

有没有更好的办法,这个逻辑可行吗?

我尝试了thirdparty 的一些网址,但无法正常工作...

任何帮助将不胜感激!

【问题讨论】:

  • 您能描述一下为什么它不起作用吗?
  • 我刚刚更新了更多信息。谢谢
  • $max: 2 的目标是什么?
  • 获得 2 个对象的限制。
  • 你能不能快点试试:[{"$match":{"name":"foo"}}, {"$limit": 2}] ?

标签: c# mongodb


【解决方案1】:

聚合管道是一个阶段数组,因此如果您想拥有灵活的端点,则需要传递一个数组。每个表示单个管道的 JSON 在根级别只能有一个字段,并且该属性应该表示管道阶段名称,例如 $match。这就是为什么您使用 $max 的示例不起作用的原因。

更重要的是,如果您想限制为2 对象,您应该使用$limit 而不是$max(用于聚合数据)。所以你的聚合管道应该是这样的:

[{"$match":{"name":"foo"}},{"$limit":2}]

由于您必须将数组而不是单个字符串传递给 API,因此使用 POST 而不是 GET 端点并将该数组传递到请求的正文中会更容易

public class Payload
{
    public string[] Pipes { get; set; }
}

[HttpPost("aggregate")]
public async Task<IActionResult> GetByAggregate([FromBody]Payload payload)
{
    if (!string.IsNullOrEmpty(pipes))
    {
        var p = PipelineDefinition<T, T>.Create(payload.Pipes.Select(BsonDocument.Parse));

        IAsyncCursor<T> result = await _monsterService.AggregateAsync(p);

        return Ok(result.ToListAsync());
    }

    return NotFound();
}

然后您可以发送POST 请求,正文如下:

{
    "pipes": [ "{\"$match\":{\"name\":\"foo\"}}","{\"$limit\":2}"  ]
}

【讨论】:

  • 好的,但是他们是怎么做到的restdb.io。我认为他们修剪字符串以获得管道阶段......?
  • 如果我不想使用 Linq 怎么办?
  • 是的,您可以将所有管道作为一个字符串传递,然后用某个分隔符拆分该字符串 - 这是可能的。这里不需要 Linq,我想展示的是您需要在管道中使用多个 BsonDocuments 来过滤然后限制结果。是的,您可以检查数组是否不为空以及 BsonDocument.Parse 是否适用于所有元素
猜你喜欢
  • 2018-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-04
  • 1970-01-01
  • 2021-01-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多