【问题标题】:Elasticsearch Vs MongoDB Aggregation - Development Comparison with ExampleElasticsearch Vs MongoDB Aggregation - 开发对比与示例
【发布时间】:2020-02-10 17:57:57
【问题描述】:

我正在 NodeJS 平台中将 MongoDB Query 转换为 Elasticsearch。在开发过程中,我在使用 Elasticsearch Query 中的分组和过滤数据(获取嵌套对象,如 hits.hits._source)时遇到了一些困难,就像我们在 MongoDB Query 中所做的那样。

例子:-

UserModel.aggregate([
    {
        $match: {
            uId: req.body.uId, timestamp: { $gte: req.body.date, $lte: new Date() }
        },
    },
    {
        $group: {
            _id: "$eId",
            location: {
                $push: {
                    time: "$timestamp", lat: "$lat"
                }
            },
            timestamp: {
                $push: "$timestamp"
            },
            testId: { $first: "$testId" },
        }
    },
    {
        $project: {
            eId: 1, location: 1, testId: 1, max: { $max: "$timestamp" }
        }
    },
    { $unwind: { path: "$location", preserveNullAndEmptyArrays: true } },
    {
        $redact: {
            $cond: {
                if: { $eq: ["$location.time", "$max"] },
                then: "$$DESCEND",
                else: "$$PRUNE"
            }
        }
    },
    {
        $project: {
            eId: 1, latitude: "$location.lat", testId: 1
        }
    },
]).exec(function (err, result) {
    console.log(result)
});

Elasticsearch 中的等效查询是什么? 我正在寻找具有最小嵌套响应的分组、展开和投影(MongoDB 概念到 Elasticsearch)所需数据的解决方案。 提前致谢。

编辑:-

添加 Elasticsearch 文档:-

{
          "timestamp": "2019-10-08T:02:50:15.54Z",
          "status" : 1,
          "eId": "5d5d7ce0c89852e7bad4a407",
          "location": [
            2.000,
            34.5664111801
          ],
          "zId": "5d5d7ce0c89852e7bad4a4ef"
},
{
          "timestamp": "2019-10-09T:02:50:15.54Z",
          "status" : 1,
          "eId": "5d5d7ce0c89852e7bad4a408",
          "location": [
            2.100,
            35.5664111801
          ],
          "zId": "5d5d7ce0c89852e7bad4a4ef"
},
{
          "timestamp": "2019-10-09T:03:50:15.54Z",
          "status" : 1,
          "eId": "5d5d7ce0c89852e7bad4a407",
          "location": [
            4.100,
            35.5664111801
          ],
          "zId": "5d5d7ce0c89852e7bad4a4ef"
},
{
          "timestamp": "2019-10-09T:03:40:15.54Z",
          "status" : 1,
          "eId": "5d5d7ce0c89852e7bad4a407",
          "location": [
            2.100,
            35.5664111801
          ],
          "zId": "5d5d7ce0c89852e7bad4a4e1"
},
{
          "timestamp": "2019-10-10T:03:40:15.54Z",
          "status" : 1,
          "eId": "5d5d7ce0c89852e7bad4a407",
          "location": [
            3.100,
            35.5664111801
          ],
          "zId": "5d5d7ce0c89852e7bad4a4e1"
}
  1. 匹配状态 =1,并按 eId 分组
  2. 根据该结果,按时间戳分组并获取最大时间戳值

预期结果:-

[
        {
            "_id": "5d5d7ce0c89852e7bad4a407",
            "max": "2019-10-10T:03:40:15.54Z", // max timestamp
            "zId": [
                "5d5d7ce0c89852e7bad4a4e1",
                "5d5d7ce0c89852e7bad4a4ef"
            ]
        },
        {
            "_id": "5d5d7ce0c89852e7bad4a408",
            "max": "2019-10-09T:02:50:15.54Z",
            "zId": [
                "5d5d7ce0c89852e7bad4a4ef"
            ]
        }, // ...etc 

    ]

【问题讨论】:

  • 我对mongoDb的了解不够,无法回答你的问题,但如果你能提供一组文档和预期的结果,我可以试着给你一个答案。
  • @Pierre-NicolasMougel 谢谢。将添加文档。
  • @Pierre-NicolasMougel 添加了数据。你能帮帮我吗?

标签: javascript node.js mongodb elasticsearch


【解决方案1】:

感谢您的文件。可悲的是,我不知道有什么方法可以只检索具有最大时间戳字段值的文档。

以下查询将允许您按status 过滤并按eId 分组,然后获取最大时间戳值,但它不会返回具有最大时间戳值的文档。

{
    "size": 0,
    "query": {
        "term": {
            "status": 1
        }
    },
    "aggregations": {
        "eId_group": {
            "terms": {
                "field": "eId"
            },
            "aggregations": {
                "max_timestamp": {
                    "max": {
                        "field": "timestamp"
                    }
                }
            }
        }
    }
}

第二个查询使用top_hits 聚合来检索按eId 分组的文档。返回的文档按时间戳值递减排序,因此具有最大时间戳的文档将是第一个,但您也可能获得具有不同时间戳的文档。

{
    "size": 0,
    "query": {
        "term": {
            "status": 1
        }
    },
    "aggregations": {
        "eId_group": {
            "terms": {
                "field": "eId"
            },
            "aggregations": {
                "max_timestamp": {
                    "max": {
                        "field": "timestamp"
                    }
                },
                "top_documents": {
                    "top_hits": {
                        "size": 20,
                        "sort": { "timestamp": "desc"}
                    }
                }
            }
        }
    }
}

我对索引使用了以下映射

PUT /test_index
{
    "mappings": {
        "properties": {
            "timestamp": {
                "type": "date"
            },
            "eId": {
                "type": "keyword"
            },
            "zId": {
                "type": "keyword"
            },
            "status": {
                "type": "keyword"
            }
        }
    }
}

【讨论】:

  • 此查询将在正文中:{} 对吗?而且我也收到错误,默认情况下,[illegal_argument_exception] Fielddata 在文本字段中被禁用。在 [employeeId] 上设置 fielddata=true,以便通过反转倒排索引将 fielddata 加载到内存中。请注意,这可能会占用大量内存。或者,改用关键字字段。注意:- 在所有字段中添加关键字。但仍然出现一些错误。
  • 是的,您应该为执行聚合的字段使用keyword 类型。如果您也在搜索此字段,则可以使用其他类型创建子字段。还有哪些错误?
  • 您的时间戳值也未正确格式化为 ISO 8601 表示法。您应该删除 T 之后的 : 或者您可以更改日期解析格式。我已经用我使用的映射更新了答案。
猜你喜欢
  • 1970-01-01
  • 2021-04-20
  • 2019-01-28
  • 2012-04-25
  • 1970-01-01
  • 1970-01-01
  • 2019-11-08
  • 2016-12-15
  • 2021-01-05
相关资源
最近更新 更多