aboutsummaryrefslogtreecommitdiff
path: root/icing/scoring/advanced_scoring/advanced-scorer_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'icing/scoring/advanced_scoring/advanced-scorer_test.cc')
-rw-r--r--icing/scoring/advanced_scoring/advanced-scorer_test.cc208
1 files changed, 206 insertions, 2 deletions
diff --git a/icing/scoring/advanced_scoring/advanced-scorer_test.cc b/icing/scoring/advanced_scoring/advanced-scorer_test.cc
index b3a47ba..c962bc5 100644
--- a/icing/scoring/advanced_scoring/advanced-scorer_test.cc
+++ b/icing/scoring/advanced_scoring/advanced-scorer_test.cc
@@ -65,7 +65,12 @@ class AdvancedScorerTest : public testing::Test {
ICING_ASSERT_OK_AND_ASSIGN(
DocumentStore::CreateResult create_result,
DocumentStore::Create(&filesystem_, doc_store_dir_, &fake_clock_,
- schema_store_.get()));
+ schema_store_.get(),
+ /*force_recovery_and_revalidate_documents=*/false,
+ /*namespace_id_fingerprint=*/false,
+ PortableFileBackedProtoLog<
+ DocumentWrapper>::kDeflateCompressionLevel,
+ /*initialize_stats=*/nullptr));
document_store_ = std::move(create_result.document_store);
// Creates a simple email schema
@@ -77,8 +82,31 @@ class AdvancedScorerTest : public testing::Test {
.SetDataTypeString(
TermMatchType::PREFIX,
StringIndexingConfig::TokenizerType::PLAIN)
- .SetDataType(TYPE_STRING)
.SetCardinality(CARDINALITY_OPTIONAL)))
+ .AddType(SchemaTypeConfigBuilder()
+ .SetType("person")
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("emailAddress")
+ .SetDataTypeString(
+ TermMatchType::PREFIX,
+ StringIndexingConfig::TokenizerType::PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL))
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("name")
+ .SetDataTypeString(
+ TermMatchType::PREFIX,
+ StringIndexingConfig::TokenizerType::PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL))
+
+ .AddProperty(
+ PropertyConfigBuilder()
+ .SetName("phoneNumber")
+ .SetDataTypeString(
+ TermMatchType::PREFIX,
+ StringIndexingConfig::TokenizerType::PLAIN)
+ .SetCardinality(CARDINALITY_OPTIONAL)))
.Build();
ICING_ASSERT_OK(schema_store_->SetSchema(test_email_schema));
@@ -135,6 +163,27 @@ ScoringSpecProto CreateAdvancedScoringSpec(
return scoring_spec;
}
+PropertyWeight CreatePropertyWeight(std::string path, double weight) {
+ PropertyWeight property_weight;
+ property_weight.set_path(std::move(path));
+ property_weight.set_weight(weight);
+ return property_weight;
+}
+
+TypePropertyWeights CreateTypePropertyWeights(
+ std::string schema_type, std::vector<PropertyWeight>&& property_weights) {
+ TypePropertyWeights type_property_weights;
+ type_property_weights.set_schema_type(std::move(schema_type));
+ type_property_weights.mutable_property_weights()->Reserve(
+ property_weights.size());
+
+ for (PropertyWeight& property_weight : property_weights) {
+ *type_property_weights.add_property_weights() = std::move(property_weight);
+ }
+
+ return type_property_weights;
+}
+
TEST_F(AdvancedScorerTest, InvalidAdvancedScoringSpec) {
// Empty scoring expression for advanced scoring
ScoringSpecProto scoring_spec;
@@ -541,6 +590,161 @@ TEST_F(AdvancedScorerTest, ChildrenScoresFunctionScoreExpression) {
Eq(default_score));
}
+TEST_F(AdvancedScorerTest, PropertyWeightsFunctionScoreExpression) {
+ DocumentProto test_document_1 =
+ DocumentBuilder().SetKey("namespace", "uri1").SetSchema("email").Build();
+ DocumentProto test_document_2 =
+ DocumentBuilder().SetKey("namespace", "uri2").SetSchema("person").Build();
+ DocumentProto test_document_3 =
+ DocumentBuilder().SetKey("namespace", "uri3").SetSchema("person").Build();
+
+ ICING_ASSERT_OK_AND_ASSIGN(DocumentId document_id_1,
+ document_store_->Put(test_document_1));
+ ICING_ASSERT_OK_AND_ASSIGN(DocumentId document_id_2,
+ document_store_->Put(test_document_2));
+ ICING_ASSERT_OK_AND_ASSIGN(DocumentId document_id_3,
+ document_store_->Put(test_document_3));
+
+ ScoringSpecProto spec_proto = CreateAdvancedScoringSpec("");
+
+ *spec_proto.add_type_property_weights() = CreateTypePropertyWeights(
+ /*schema_type=*/"email",
+ {CreatePropertyWeight(/*path=*/"subject", /*weight=*/1.0)});
+ *spec_proto.add_type_property_weights() = CreateTypePropertyWeights(
+ /*schema_type=*/"person",
+ {CreatePropertyWeight(/*path=*/"emailAddress", /*weight=*/0.5),
+ CreatePropertyWeight(/*path=*/"name", /*weight=*/0.8),
+ CreatePropertyWeight(/*path=*/"phoneNumber", /*weight=*/1.0)});
+
+ // Let the hit for test_document_1 match property "subject".
+ // So this.propertyWeights() for test_document_1 will return [1].
+ DocHitInfo doc_hit_info_1 = DocHitInfo(document_id_1);
+ doc_hit_info_1.UpdateSection(0);
+
+ // Let the hit for test_document_2 match properties "emailAddress" and "name".
+ // So this.propertyWeights() for test_document_2 will return [0.5, 0.8].
+ DocHitInfo doc_hit_info_2 = DocHitInfo(document_id_2);
+ doc_hit_info_2.UpdateSection(0);
+ doc_hit_info_2.UpdateSection(1);
+
+ // Let the hit for test_document_3 match properties "emailAddress", "name" and
+ // "phoneNumber". So this.propertyWeights() for test_document_3 will return
+ // [0.5, 0.8, 1].
+ DocHitInfo doc_hit_info_3 = DocHitInfo(document_id_3);
+ doc_hit_info_3.UpdateSection(0);
+ doc_hit_info_3.UpdateSection(1);
+ doc_hit_info_3.UpdateSection(2);
+
+ spec_proto.set_advanced_scoring_expression("min(this.propertyWeights())");
+ ICING_ASSERT_OK_AND_ASSIGN(
+ std::unique_ptr<AdvancedScorer> scorer,
+ AdvancedScorer::Create(spec_proto,
+ /*default_score=*/10, document_store_.get(),
+ schema_store_.get()));
+ // min([1]) = 1
+ EXPECT_THAT(scorer->GetScore(doc_hit_info_1, /*query_it=*/nullptr), Eq(1));
+ // min([0.5, 0.8]) = 0.5
+ EXPECT_THAT(scorer->GetScore(doc_hit_info_2, /*query_it=*/nullptr), Eq(0.5));
+ // min([0.5, 0.8, 1.0]) = 0.5
+ EXPECT_THAT(scorer->GetScore(doc_hit_info_3, /*query_it=*/nullptr), Eq(0.5));
+
+ spec_proto.set_advanced_scoring_expression("max(this.propertyWeights())");
+ ICING_ASSERT_OK_AND_ASSIGN(
+ scorer,
+ AdvancedScorer::Create(spec_proto,
+ /*default_score=*/10, document_store_.get(),
+ schema_store_.get()));
+ // max([1]) = 1
+ EXPECT_THAT(scorer->GetScore(doc_hit_info_1, /*query_it=*/nullptr), Eq(1));
+ // max([0.5, 0.8]) = 0.8
+ EXPECT_THAT(scorer->GetScore(doc_hit_info_2, /*query_it=*/nullptr), Eq(0.8));
+ // max([0.5, 0.8, 1.0]) = 1
+ EXPECT_THAT(scorer->GetScore(doc_hit_info_3, /*query_it=*/nullptr), Eq(1));
+
+ spec_proto.set_advanced_scoring_expression("sum(this.propertyWeights())");
+ ICING_ASSERT_OK_AND_ASSIGN(
+ scorer,
+ AdvancedScorer::Create(spec_proto,
+ /*default_score=*/10, document_store_.get(),
+ schema_store_.get()));
+ // sum([1]) = 1
+ EXPECT_THAT(scorer->GetScore(doc_hit_info_1, /*query_it=*/nullptr), Eq(1));
+ // sum([0.5, 0.8]) = 1.3
+ EXPECT_THAT(scorer->GetScore(doc_hit_info_2, /*query_it=*/nullptr), Eq(1.3));
+ // sum([0.5, 0.8, 1.0]) = 2.3
+ EXPECT_THAT(scorer->GetScore(doc_hit_info_3, /*query_it=*/nullptr), Eq(2.3));
+}
+
+TEST_F(AdvancedScorerTest,
+ PropertyWeightsFunctionScoreExpressionUnspecifiedWeights) {
+ DocumentProto test_document_1 =
+ DocumentBuilder().SetKey("namespace", "uri1").SetSchema("email").Build();
+ DocumentProto test_document_2 =
+ DocumentBuilder().SetKey("namespace", "uri2").SetSchema("person").Build();
+
+ ICING_ASSERT_OK_AND_ASSIGN(DocumentId document_id_1,
+ document_store_->Put(test_document_1));
+ ICING_ASSERT_OK_AND_ASSIGN(DocumentId document_id_2,
+ document_store_->Put(test_document_2));
+
+ ScoringSpecProto spec_proto = CreateAdvancedScoringSpec("");
+
+ // The entry for type "email" is missing, so every properties in "email"
+ // should get weight 1.0.
+ // The weight of "phoneNumber" in "person" type is unspecified, which should
+ // default to 1/2 = 0.5
+ *spec_proto.add_type_property_weights() = CreateTypePropertyWeights(
+ /*schema_type=*/"person",
+ {CreatePropertyWeight(/*path=*/"emailAddress", /*weight=*/1.0),
+ CreatePropertyWeight(/*path=*/"name", /*weight=*/2)});
+
+ // Let the hit for test_document_1 match property "subject".
+ // So this.propertyWeights() for test_document_1 will return [1].
+ DocHitInfo doc_hit_info_1 = DocHitInfo(document_id_1);
+ doc_hit_info_1.UpdateSection(0);
+
+ // Let the hit for test_document_2 match properties "emailAddress", "name" and
+ // "phoneNumber". So this.propertyWeights() for test_document_3 will return
+ // [0.5, 1, 0.5].
+ DocHitInfo doc_hit_info_2 = DocHitInfo(document_id_2);
+ doc_hit_info_2.UpdateSection(0);
+ doc_hit_info_2.UpdateSection(1);
+ doc_hit_info_2.UpdateSection(2);
+
+ spec_proto.set_advanced_scoring_expression("min(this.propertyWeights())");
+ ICING_ASSERT_OK_AND_ASSIGN(
+ std::unique_ptr<AdvancedScorer> scorer,
+ AdvancedScorer::Create(spec_proto,
+ /*default_score=*/10, document_store_.get(),
+ schema_store_.get()));
+ // min([1]) = 1
+ EXPECT_THAT(scorer->GetScore(doc_hit_info_1, /*query_it=*/nullptr), Eq(1));
+ // min([0.5, 1, 0.5]) = 0.5
+ EXPECT_THAT(scorer->GetScore(doc_hit_info_2, /*query_it=*/nullptr), Eq(0.5));
+
+ spec_proto.set_advanced_scoring_expression("max(this.propertyWeights())");
+ ICING_ASSERT_OK_AND_ASSIGN(
+ scorer,
+ AdvancedScorer::Create(spec_proto,
+ /*default_score=*/10, document_store_.get(),
+ schema_store_.get()));
+ // max([1]) = 1
+ EXPECT_THAT(scorer->GetScore(doc_hit_info_1, /*query_it=*/nullptr), Eq(1));
+ // max([0.5, 1, 0.5]) = 1
+ EXPECT_THAT(scorer->GetScore(doc_hit_info_2, /*query_it=*/nullptr), Eq(1));
+
+ spec_proto.set_advanced_scoring_expression("sum(this.propertyWeights())");
+ ICING_ASSERT_OK_AND_ASSIGN(
+ scorer,
+ AdvancedScorer::Create(spec_proto,
+ /*default_score=*/10, document_store_.get(),
+ schema_store_.get()));
+ // sum([1]) = 1
+ EXPECT_THAT(scorer->GetScore(doc_hit_info_1, /*query_it=*/nullptr), Eq(1));
+ // sum([0.5, 1, 0.5]) = 2
+ EXPECT_THAT(scorer->GetScore(doc_hit_info_2, /*query_it=*/nullptr), Eq(2));
+}
+
TEST_F(AdvancedScorerTest, InvalidChildrenScoresFunctionScoreExpression) {
const double default_score = 123;