truy vấn boolearch kết hợp phải với OR


181

Tôi hiện đang cố gắng chuyển một ứng dụng dựa trên solr sang elaticsearch.

Tôi có truy vấn lucene này

(( 
    name:(+foo +bar) 
    OR info:(+foo +bar) 
)) AND state:(1) AND (has_image:(0) OR has_image:(1)^100)

Theo tôi hiểu thì đây là sự kết hợp của các mệnh đề PHẢI kết hợp với boolean HOẶC:

"Nhận tất cả các tài liệu có chứa (tên foo AND trong tên) HOẶC (thanh foo AND trong thông tin). Sau đó, bộ lọc kết quả theo trạng thái điều kiện = 1 và tăng tài liệu có hình ảnh."

Tôi đã cố gắng sử dụng truy vấn bool với PHẢI nhưng tôi không nhận được boolean HOẶC các mệnh đề phải. Đây là những gì tôi có:

GET /test/object/_search
{
  "from": 0,
  "size": 20,
  "sort": {
    "_score": "desc"
  },
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "foo"
          }
        },
        {
          "match": {
            "name": "bar"
          }
        }
      ],
      "must_not": [],
      "should": [
        {
          "match": {
            "has_image": {
              "query": 1,
              "boost": 100
            }
          }
        }
      ]
    }
  }
}

Như bạn có thể thấy, PHẢI điều kiện cho "thông tin" bị thiếu.

Có ai có giải pháp không?

Cảm ơn bạn rất nhiều.

** CẬP NHẬT **

Tôi đã cập nhật truy vấn elaticsearch của mình và thoát khỏi điểm số chức năng đó. Vấn đề cơ sở của tôi vẫn tồn tại.


1
Có một tài liệu tốt về việc kết hợp các truy vấn của FlexSearch tại đây: thun.co / guide / en / elaticsearch / guide / civerse / ám
Mr.Coffee

Câu trả lời:


426
  • HOẶC được đánh vần nên
  • được đánh vần phải
  • NOR được đánh vần nên_not

Thí dụ:

Bạn muốn xem tất cả các mục (tròn VÀ (màu đỏ HOẶC màu xanh)):

{
    "query": {
        "bool": {
            "must": [
                {
                    "term": {"shape": "round"}
                },
                {
                    "bool": {
                        "should": [
                            {"term": {"color": "red"}},
                            {"term": {"color": "blue"}}
                        ]
                    }
                }
            ]
        }
    }
}

Bạn cũng có thể thực hiện các phiên bản OR phức tạp hơn, ví dụ: nếu bạn muốn khớp ít nhất 3 trên 5, bạn có thể chỉ định 5 tùy chọn trong "nên" và đặt "tối thiểu" là 3.

Cảm ơn Glen Thompson và Sebastialonso vì đã tìm thấy nơi làm tổ của tôi không hoàn toàn đúng trước đây.

Cũng xin cảm ơn Fatmajk vì đã chỉ ra rằng "thuật ngữ" trở thành "khớp" trong ElasticSearch 6.


2
Sẽ kéo shouldcấp trên bool, và bao gồm một minimum_should_match: 1tác phẩm?
Sid

18
Khi tôi thử ví dụ này, tôi nhận lại [term] malformed query, expected [END_OBJECT] but found [FIELD_NAME]. Đây có phải là phiên bản nào đó phụ thuộc?
DanneJ

26
Tại sao họ không thêm một ví dụ đơn giản và giải thích như vậy trong các tài liệu! Ví dụ từ tài liệu rất khó hiểu.
Nikhil Owalekar

21
Sau 6 tháng, đọc tất cả tài liệu Đàn hồi, đây là lần đầu tiên tôi hoàn toàn hiểu cách thực hiện logic boolean. Tài liệu chính thức thiếu sự rõ ràng trong quan điểm của tôi.
Sebastialonso

3
@Amir Những gì không chính xác tôi có thể làm sạch cho bạn? Trong ngữ cảnh hiển thị ở trên, mặc định minimum_shouldlà 1 và bao bọc rằng boolkết quả trong nhóm đó là đúng nếu có ít nhất một mục khớp, sai nếu không khớp. Động lực của tôi để tạo ra câu trả lời này là tôi đã giải quyết chính xác loại vấn đề này, và tài liệu có sẵn và thậm chí các câu trả lời tôi có thể tìm thấy trên các trang web như thế này là không hữu ích, vì vậy tôi tiếp tục nghiên cứu cho đến khi tôi cảm thấy nắm bắt khá chắc chắn về những gì đang xảy ra. Tôi sẵn sàng chào đón bất kỳ con trỏ mang tính xây dựng nào về cách tôi có thể cải thiện câu trả lời hơn nữa.
Daniel Fackrell

69

Cuối cùng tôi cũng có thể tạo ra một truy vấn thực hiện chính xác những gì tôi muốn có:

Một truy vấn boolean lồng nhau được lọc. Tôi không chắc tại sao điều này không được ghi lại. Có lẽ ai đó ở đây có thể nói với tôi?

Đây là truy vấn:

GET /test/object/_search
{
  "from": 0,
  "size": 20,
  "sort": {
    "_score": "desc"
  },
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must": [
            {
              "term": {
                "state": 1
              }
            }
          ]
        }
      },
      "query": {
        "bool": {
          "should": [
            {
              "bool": {
                "must": [
                  {
                    "match": {
                      "name": "foo"
                    }
                  },
                  {
                    "match": {
                      "name": "bar"
                    }
                  }
                ],
                "should": [
                  {
                    "match": {
                      "has_image": {
                        "query": 1,
                        "boost": 100
                      }
                    }
                  }
                ]
              }
            },
            {
              "bool": {
                "must": [
                  {
                    "match": {
                      "info": "foo"
                    }
                  },
                  {
                    "match": {
                      "info": "bar"
                    }
                  }
                ],
                "should": [
                  {
                    "match": {
                      "has_image": {
                        "query": 1,
                        "boost": 100
                      }
                    }
                  }
                ]
              }
            }
          ],
          "minimum_should_match": 1
        }
      }    
    }
  }
}

Trong giả SQL:

SELECT * FROM /test/object
WHERE 
    ((name=foo AND name=bar) OR (info=foo AND info=bar))
AND state=1

Xin lưu ý rằng điều này phụ thuộc vào phân tích trường tài liệu của bạn và ánh xạ cách tên = foo được xử lý nội bộ. Điều này có thể thay đổi từ một hành vi mờ nhạt đến nghiêm ngặt.

"Minimal_should_match": 1 nói rằng ít nhất một trong các câu lệnh phải đúng.

Câu lệnh này có nghĩa là bất cứ khi nào có một tài liệu trong tập kết quả có has_image: 1 thì nó được tăng theo hệ số 100. Điều này thay đổi thứ tự kết quả.

"should": [
  {
    "match": {
      "has_image": {
        "query": 1,
        "boost": 100
      }
    }
   }
 ]

Chúc vui vẻ nha các bạn :)


28
Thánh lồn Có ai có một giải pháp tốt hơn? Cảm ơn bạn đã đăng bài này, nhưng đó hoàn toàn là quá nhiều phức tạp để đạt được logic HOẶC trong một truy vấn.
nackjicholson

thnx, bạn đã cứu ngày của tôi)
cubbiu

3
Truy vấn này không chỉ dài một cách bất thường mà còn sử dụng cú pháp không dùng nữa. @ daniel-fackrell câu trả lời nên được chấp nhận.
Eric Alford

4
@EricAlford Câu trả lời này từ năm 2015 dựa trên phiên bản ES trước đó. Hãy cung cấp một giải pháp tốt hơn.
Jesse

1
Ý tưởng: Tiếp quản / fork ElasticSearch, viết lại theo cách thân thiện với người dùng, thêm ngôn ngữ truy vấn đơn giản vào đó, THẮNG! Chúng tôi chỉ cần tài trợ. Tôi vào rồi! Còn ai nữa không
Sliq

16

Đây là cách bạn có thể lồng nhiều truy vấn bool trong một truy vấn bool bên ngoài này bằng Kibana,

bool cho biết chúng ta đang sử dụng boolean

phải dành cho

nên dành cho HOẶC

GET my_inedx/my_type/_search
{
    "query" : {
       "bool": {             //bool indicates we are using boolean operator
            "must" : [       //must is for **AND**
                 {
                   "match" : {
                         "description" : "some text"  
                     }
                 },
                 {
                    "match" :{
                          "type" : "some Type"
                     }
                 },
                 {
                    "bool" : {          //here its a nested boolean query
                          "should" : [  //should is for **OR**
                                 {
                                   "match" : {
                                       //ur query
                                  }
                                 },
                                 { 
                                    "match" : {} 
                                 }     
                               ]
                          }
                 }
             ]
        }
    }
}

Đây là cách bạn có thể lồng một truy vấn trong ES

Có nhiều loại trong "bool" như -

  1. Bộ lọc

  2. không được


Câu trả lời của bạn là hoàn toàn chính xác, nhưng nó hơi vụng về, đó là một gợi ý nhỏ cho bạn nếu bạn muốn - bạn phải chỉnh sửa nó đúng cách. Có lẽ nó mang lại cho bạn nhiều hơn về câu trả lời này :) Chúc một ngày tốt lành.
Dhwanil Patel

6

Gần đây tôi cũng phải giải quyết vấn đề này và sau rất nhiều thử nghiệm và lỗi tôi đã đưa ra vấn đề này (trong PHP, nhưng ánh xạ trực tiếp vào DSL):

'query' => [
    'bool' => [
        'should' => [
            ['prefix' => ['name_first' => $query]],
            ['prefix' => ['name_last' => $query]],
            ['prefix' => ['phone' => $query]],
            ['prefix' => ['email' => $query]],
            [
                'multi_match' => [
                    'query' => $query,
                    'type' => 'cross_fields',
                    'operator' => 'and',
                    'fields' => ['name_first', 'name_last']
                ]
            ]
        ],
        'minimum_should_match' => 1,
        'filter' => [
            ['term' => ['state' => 'active']],
            ['term' => ['company_id' => $companyId]]
        ]
    ]
]

Ánh xạ tới thứ gì đó như thế này trong SQL:

SELECT * from <index> 
WHERE (
    name_first LIKE '<query>%' OR
    name_last LIKE '<query>%' OR
    phone LIKE  '<query>%' OR
    email LIKE '<query>%'
)
AND state = 'active'
AND company_id = <query>

Chìa khóa trong tất cả điều này là minimum_should_matchcài đặt. Không có điều này filterhoàn toàn ghi đè lên should.

Hy vọng điều này sẽ giúp được ai đó!


0
$filterQuery = $this->queryFactory->create(QueryInterface::TYPE_BOOL, ['must' => $queries,'should'=>$queriesGeo]);

Trong mustbạn cần thêm mảng điều kiện truy vấn mà bạn muốn làm việc ANDvà trong shouldbạn cần thêm điều kiện truy vấn mà bạn muốn làm việc với OR.

Bạn có thể kiểm tra điều này: https://github.com/Smile-SA/elaticsuite/issues/972


0

Nếu bạn đang sử dụng trình phân tích cú pháp truy vấn mặc định hoặc Lucene của Solr, bạn luôn có thể đặt nó vào một truy vấn chuỗi truy vấn:

POST test/_search
{
  "query": {
    "query_string": {
      "query": "(( name:(+foo +bar) OR info:(+foo +bar)  )) AND state:(1) AND (has_image:(0) OR has_image:(1)^100)"
    }
  }
}

Điều đó nói rằng, bạn có thể muốn sử dụng truy vấn boolean , như truy vấn bạn đã đăng hoặc thậm chí là kết hợp cả hai.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.