悟空,拿我的打狗棒来

省市区分块排序要怎么查?展示结果是:本省本市的、本省外市的、全国的,而且都是按照倒序排,本省本市的排前面,这个要怎么弄???

Elasticsearch | 作者 herryhaixiao | 发布于2016年10月11日 | 阅读数:4089

各位大牛:帮我看看这种分块查询要怎么写?
满足要求的排前面,并且是按照时间倒序;
provinceName省份,cityName城市,updatedTime时间。就是这个时间排序分块排,不知道怎么弄。
本市项目发布需求(如果有多条,按发布时间倒序)>本省项目发布需求(剔除本市数据,如果有多条,按发布时间倒序)>全国项目发布需求(剔除本市、本省数据,如果有多条,按发布时间倒序)
已邀请:

martindu - 搜披露创始人

赞同来自: qq123

试一下BoolQuery和FunctionScoreQuery组合。将provicnceName和cityName加入到BoolQuery的Should里面,然后给cityName的Boost设一个较大值,provinceName设一个次大值。整个BoolQuery再作为FunctionScoreQuery的子Query,用GaussDecay,拉一个非常平缓的时间段(比如10年),这样确保时间不会成为排序的主要因素。
 
这种方法的准确程度取决于参数的设置,而且有时候打不到100%精确。
 
另一种方法,你也写了三种情况实际上是互斥的,所以可以分为三次请求查询。每个请求把自己的部分负责好就可以。前端再组合就是了。

martindu - 搜披露创始人

赞同来自:

我用c#写了一段,我同时把c#代码和http request供你参考:
 
先是生成测试数据的代码,找了12个城市随机日期和项目名称搞了144个数据:
static void GenerateProjectInfo()
{
Dictionary<string, List<string>> dictLocation = new Dictionary<string, List<string>>();
dictLocation.Add("北京市", new List<string>() { "海淀区", "朝阳区", "西城区" });
dictLocation.Add("辽宁省", new List<string>() { "沈阳市", "大连市", "本溪市" });
dictLocation.Add("山东省", new List<string>() { "济南市", "济宁市", "青岛市" });
dictLocation.Add("江苏省", new List<string>() { "南京市", "苏州市", "无锡市" });

string strUri = "http://192.168.1.100:9200&quot;;
string strIndex = "projecttest";
var settings = new ConnectionSettings(new SingleNodeConnectionPool(new Uri(strUri))).DefaultIndex(strIndex);
ElasticClient ecTest = new ElasticClient(settings);

var response = ecTest.IndexExists(strIndex);
if (!response.Exists)
{
ecTest.CreateIndex(strIndex, c => c
.Settings(s => s
.NumberOfReplicas(0)
.NumberOfShards(1))
.Mappings(mp => mp
.Map<ProjectInfo>(m => m
.AutoMap()
.AllField(af => af.Enabled(false)))));
}


List<ProjectInfo> projects = new List<ProjectInfo>( );
Random rand = new Random(100);
foreach (var pair in dictLocation)
{
foreach (var city in pair.Value)
{
for (int i = 0; i < 12; i++)
{
DateTime dtePublish = new DateTime(2016, 1, 1).AddDays(rand.Next(300));
string strProjectName = "";
if (i%3 == 0)
{
strProjectName = "设计项目";
}
else if (i%3 == 1)
{
strProjectName = "开发项目";
}
else if (i%3 == 2)
{
strProjectName = "测试项目";
}
ProjectInfo project = new ProjectInfo()
{
ProjectName = pair.Key + city + strProjectName,
ProvinceName = pair.Key,
CityName = city,
PublishDate = dtePublish
};
projects.Add(project);
}
}
}

ecTest.IndexMany(projects);

}
然后是构建查询,以“测试项目”为关键字,并预设本市为沈阳市、本省为辽宁省。注意city的权重给了10,province给了5。Gauss的时间段是3600天。
 
static void SearchProject()
{
string projectName = "测试项目";
string province = "辽宁省";
string city = "沈阳市";
BoolQuery queryBool = new BoolQuery()
{
Must = new List<QueryContainer>()
{
new MatchPhraseQuery()
{
Field = "projectName",
Query = projectName
}
},
Should = new List<QueryContainer>()
{
new TermQuery()
{
Field = "provinceName",
Value = province,
Boost = 5
},
new TermQuery()
{
Field = "cityName",
Value = city,
Boost = 10
}
}
};
FunctionScoreQuery querySort = new FunctionScoreQuery()
{
Query = queryBool,
Functions = new List<IScoreFunction>
{
new GaussDateDecayFunction
{
Field = "publishDate",
Offset = TimeSpan.FromDays(0),
Scale = TimeSpan.FromDays(3600),
Origin = DateTime.Now
}
},
};

SearchRequest<ProjectInfo> request = new SearchRequest<ProjectInfo>()
{
Size = 20,
Query = querySort
};

string strUri = "http://192.168.1.100:9200&quot;;
string strIndex = "projecttest";
var settings = new ConnectionSettings(new SingleNodeConnectionPool(new Uri(strUri))).DefaultIndex(strIndex);
ElasticClient ecTest = new ElasticClient(settings);
var response = ecTest.Search<ProjectInfo>(request);

}
查询请求的httpRequest:
{
  "size": 20,
  "query": {
    "function_score": {
      "functions": [
        {
          "gauss": {
            "publishDate": {
              "origin": "2016-10-12T17:00:20.800922+08:00",
              "scale": "514.29w",
              "offset": 0
            }
          }
        }
      ],
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "projectName": {
                  "query": "测试项目",
                  "type": "phrase"
                }
              }
            }
          ],
          "should": [
            {
              "term": {
                "provinceName": {
                  "value": "辽宁省",
                  "boost": 5
                }
              }
            },
            {
              "term": {
                "cityName": {
                  "value": "沈阳市",
                  "boost": 10
                }
              }
            }
          ]
        }
      }
    }
  }
}
查询结果就是首先是4个辽宁沈阳测试项目,然后是其他辽宁省的测试项目,然后是其他省的项目。
希望能帮到你哈。
 

要回复问题请先登录注册