【问题标题】:Elasticsearch Query on multiple object fields of an Array of ObjectsElasticsearch 查询对象数组的多个对象字段
【发布时间】:2021-06-23 07:21:33
【问题描述】:

我有一个如下所示的产品文档:

{
        "_index": "productss",
        "_type": "_doc",
        "_id": "2fb60b1880f0251af4340af009",
        "_score": 5.0262785,
        "_source": {
            
            "prepTime": {
                "durationType": "Min",
                "value": 8,
                "imageUrl": ""
            },
            "shopId": "CCXow8ALRDrALRSKFC",
            "productTimings": [
                {
                    "startHour": 8,
                    "endHour": 9,
                    "startMin": 30,
                    "endMin": 45,
                    "dayOfWeek": [
                        "Mon",
                        "Tue",
                        "Wed",
                        "Thu",
                        "Fri"
                    ]
                },
                {
                    "startHour": 16,
                    "endHour": 18,
                    "startMin": 30,
                    "endMin": 45,
                    "dayOfWeek": [
                        "Sat",
                        "Sun"
                    ]
                }
            ]
            
        }
    }

我的模型看起来像这样。

const mongoosastic = require('mongoosastic');

const { Schema } = mongoose;

const Timing = new Schema({
  startHour: { type: Number, es_indexed: true },
  endHour: { type: Number, es_indexed: true },
  startMin: { type: Number, es_indexed: true },
  endMin: { type: Number, es_indexed: true },
  dayOfWeek: [{ type: String, es_indexed: true }],
});

const productsSchema = mongoose.Schema({
  _id: { type: String },
  
  prepTime : {
    durationType : { type: String, es_indexed: true },
    value : { type: Number, es_indexed: true },
    imageUrl : { type: String, es_indexed: true }
},
shopId: { type: String, es_indexed: true },
  
  productTimings: {
    type: [Timing],
    es_indexed: true,
    es_type: 'nested',
    es_include_in_parent: true,
  }
  
});

productsSchema.plugin(mongoosastic);

module.exports = mongoose.model('Products', productsSchema, 'Products');

我需要获取 startHours:Startminute 小于当前时间且 endHour:endMinute 小于当前时间的所有产品。它还应该与当前日期的 dayOfWeek 匹配。

请注意,productTimings 中可能有上午时段和晚上时段。

我已经尝试了以下方法并做到了这一点,但无法继续进行:

prodDetails = await client.search({
          index: 'productss',
          body:
          {
            query:
            {
              bool: {
              must: [
                { match: { shopId } },
                {
                  "nested": {
                    "path": "productTimings",
                    "query": {
                      "range": {
                        "productTimings.startHour": {
                          "lte": 12,

                        }
                      },
                      "range": {
                        "productTimings.endHour":{
                          "gte": 11,
                        }
                      }
                    }
                  }
                }
              ]
            }
          }

            },
          },
          from: pageno * size,
          size,
        });```

【问题讨论】:

  • 嗨,我一直在使用同一个包,mongoosastic。我面临的问题是,当我使用 es_type: 'nested' 创建嵌套索引时,在 elasticsearch 中生成和更新的映射仍然是一般的扁平对象类型。查询时出现此错误,failed to create query: [nested] nested object under path [productTimings] is not of nested type。我需要做任何额外的步骤来确保映射是嵌套类型的吗?

标签: node.js mongodb elasticsearch


【解决方案1】:

您快到了,但查询的格式严重错误。

试试这个——我已经对其进行了调整以匹配上面的示例文档:

const body = {
  size,
  from: pageno * size,
  "query": {
    "bool": {
      "must": [
        {
          "match": { shopId }
        },
        {
          "nested": {
            "path": "productTimings",
            "query": {
              "bool": {
                "must": [
                  {
                    "range": {
                      "productTimings.startHour": {
                        "gte": 8
                      }
                    }
                  },
                  {
                    "range": {
                      "productTimings.endHour": {
                        "lte": 9
                      }
                    }
                  },
                  {
                    "match": {
                      "productTimings.dayOfWeek": "Fri"
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}

prodDetails = await client.search({ 
    index: 'productss',
    body: body
})

? 提示:我建议使用 term 查询而不是 match。在此之前,我会将shopIddayOfWeek 转换为keywords。当它们被映射为String (= text) 时,它们将被standard analyzer 小写——而你不希望这样。您可能需要keyword 映射保证的区分大小写的完全匹配。

【讨论】:

  • 您好,感谢您的回复。我面临的问题是 startMin 和 endMin。如果 starttime 是 8:30 而 Endtime 是 9:45,那么 9:15 将不会获取任何结果。有没有办法连接 startHour+endHour 然后应用 grather 小于或小于范围?
  • 我尝试添加这个而不是范围查询,但出现了一些错误:{ "script": { "script": { "inline": "(String.valueOf(doc['startHour']. value) + string.valueOf(doc['startMin'].value)).intValue()
  • 如果您要使用连接字符串,请在嵌套查询中使用:Integer.parseInt(String.valueOf(doc['productTimings.startHour'].value) + String.valueOf(doc['productTimings.startMin'].value)) < params.inp
猜你喜欢
  • 1970-01-01
  • 2018-09-24
  • 1970-01-01
  • 1970-01-01
  • 2021-02-03
  • 1970-01-01
  • 1970-01-01
  • 2021-01-09
  • 2020-10-30
相关资源
最近更新 更多