skip to Main Content

I’m trying to implement a dynamic search for a huge product collection. The object has several properties including productName, subCategoryName, categoryName, brandName, etc. The user could search for products using any of these properties. The order is fixed and the first priority for a search string is to find it in productName and then subCategoryName and so on.

I used aggregate to achieve this and then unionWith to concat records that matched with other properties. It seems to work when fired as a raw query but we also need support for pagination and I’m not being able to achieve that with Spring Data MongoDB

db.product.aggregate(
[
  { $match: { "productName" : { "$regex" : "HYPER", "$options" : "i"}, 
  "companyNo" : { "$in" : [10000009]}, "status" : { "$in" : ["ACTIVE", "IN_ACTIVE", "OUT_OF_STOCK"]} }},
  { $unionWith: { coll: "product", pipeline: [{ $match: { "subCategoryName" : { "$regex" : "HYPER", "$options" : "i"},
  "companyNo" : { "$in" : [10000009]}, "status" : { "$in" : ["ACTIVE", "IN_ACTIVE", "OUT_OF_STOCK"]}} }] } },
  { $unionWith: { coll: "product", pipeline: [{ $match: { "categoryName" : { "$regex" : "HYPER", "$options" : "i"}, 
  "companyNo" : { "$in" : [10000009]}, "status" : { "$in" : ["ACTIVE", "IN_ACTIVE", "OUT_OF_STOCK"]}} }] } },
  { $unionWith: { coll: "product", pipeline: [{ $match: { "brandName" : { "$regex" : "HYPER", "$options" : "i"},
  "companyNo" : { "$in" : [10000009]}, "status" : { "$in" : ["ACTIVE", "IN_ACTIVE", "OUT_OF_STOCK"]}} }] } },
]
)

Also, this query only works if we pass the substring of the exact name. For example, the NIVEA BODY LOTION EXPRESS HYDRATION 200 ML HYPERmart product will be returned if I search with NIVEA BODY LOTION but it won’t return anything if I search with HYDRATION LOTION

A Sample Product:

{
    "_id" : ObjectId("6278c1c2f2570d6f199435b2"),
    "companyNo" : 10000009,
    "categoryName" : "BEAUTY and PERSONAL CARE",
    "brandName" : "HYPERMART",
    "productName" : "NIVEA BODY LOTION EXPRESS HYDRATION 200 ML HYPERmart",
    "productImageUrl" : "https://shop-now-bucket.s3.ap-south-1.amazonaws.com/shop-now-bucket/qa/10000009/product/BEAUTY%20%26%20PERSONAL%20CARE/HYPERMART/NIVEA%20BODY%20LOTION%20EXPRESS%20HYDRATION%20200%20ML/temp1652081080302.jpeg",
    "compressProductImageUrl" : "https://shop-now-bucket.s3.ap-south-1.amazonaws.com/shop-now-bucket/qa/10000009/product/BEAUTY%20%26%20PERSONAL%20CARE/HYPERMART/NIVEA%20BODY%20LOTION%20EXPRESS%20HYDRATION%20200%20ML/temp1652081080302.jpeg",
    "productPrice" : 249.0,
    "status" : "ACTIVE",
    "subCategoryName" : "BODY LOTION & BODY CREAM",
    "defaultDiscount" : 0.0,
    "discount" : 7.0,
    "description" : "Give your skin fast-absorbing moisturisation and make it noticeably smoother for 48-hours with Nivea Express Hydration Body Lotion. The formula with Sea Minerals and Hydra IQ supplies your skin with moisture all day. The new improved formula contains Deep Moisture Serum to lock in deep moisture leaving you with soft and supple skin.",
    "afterDiscountPrice" : 231.57,
    "taxPercentage" : 1.0,
    "availableQuantity" : NumberLong(100),
    "packingCharges" : 0.0,
    "available" : true,
    "featureProduct" : false,
    "wholesaleProduct" : false,
    "rewards" : NumberLong(0),
    "createAt" : ISODate("2022-05-09T07:24:40.286Z"),
    "createdBy" : "companyAdmin_@[email protected]",
    "isBulkUpload" : true,
    "buyPrice" : 0.0,
    "privateProduct" : false,
    "comboProduct" : false,
    "subscribable" : false,
    "discountAdded" : false,
    "_class" : "com.apptmart.product.entity.Product"
}

I’m new to MongoDB. any references will be appretiated.

2

Answers


  1. Checkout mongodb’s search indexes. You can create a search index with the needed fields to search by, and then you can add a $search stage to your aggregation. You can use the already built in dynamic tech search functionality. If you’re using mongodb atlas, I suggest looking at the atlas text search docs!

    To address your auto complete needs, you can set the index to allow for autocompletions (i.e – you type "hello" and the product "hello world" shows up). In addition you can implement fuzzy searches and have other neat configurations to allow for filtering alongside the text search.

    text search docs

    atlas text search docs

    // example search index to be added to mongodb atlas
    
    {
      "analyzer": "lucene.standard",
      "searchAnalyzer": "lucene.standard",
      "mappings": {
        "dynamic": true,
        "fields": {
          "_id": {
            "type": "objectId"
          },
          "title": {
            "type": "autocomplete"
          },
          "subTitle": {
            "type": "autocomplete"
          }
        }
      }
    }
    
    // example aggregation
    
    const userSearchText = 'some search';
    
    db.someCollection.aggregate([
      {
        $search: {
          should: [
            autocomplete: {
              query: userSearchText,
              path: 'title',
              fuzzy: {
                maxEdits: 2,
                prefixLength: 2
              }
            },
            autocomplete: {
              query: userSearchText,
              path: 'subTitle',
              fuzzy: {
                maxEdits: 2,
                prefixLength: 2
              }
            }
          ]
        }
      }
    ])
    

    Apologies for any typos in the code

    Also take a look at the different pipeline options that can be used:
    pipeline search options

    Login or Signup to reply.
  2. Here is my working example in Spring Boot.

    https://github.com/ConsciousObserver/MongoAggregationTest

    You can invoke the /product REST service using following command

    http://localhost:8080/products?productName=product&brandName=BRAND1&categoryName=CATEGORY2&subCategoryName=SUB_CATEGORY3&pageNumber=0&pageSize=10
    

    Implementation supports following

    1. Text search on productName (Searches by words, needs text search index)
    2. Exact match on brandName, categoryName and subCategoryName
    3. Pagination using pageNumber and pageSize

    All of it is implemented using Spring Data APIs. I generally avoid writing native queries in code, as they are not validated at compile time.

    All classes are added to one Java file, it’s just a sample so it’s better to keep everything in one place.

    Adding code below in case GitHub repository goes down.

    pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.7.4</version>
            <relativePath /> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.example</groupId>
        <artifactId>MongoAggregationTest</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>MongoAggregationTest</name>
        <description>MongoAggregationTest</description>
        <properties>
            <java.version>1.8</java.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-mongodb</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-validation</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <excludes>
                            <exclude>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                            </exclude>
                        </excludes>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

    MongoAggregationTestApplication.java

    package com.example;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.annotation.PostConstruct;
    import javax.validation.constraints.Max;
    import javax.validation.constraints.Min;
    
    import org.bson.BsonDocument;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.data.annotation.Id;
    import org.springframework.data.mongodb.core.MongoTemplate;
    import org.springframework.data.mongodb.core.aggregation.Aggregation;
    import org.springframework.data.mongodb.core.aggregation.AggregationResults;
    import org.springframework.data.mongodb.core.aggregation.LimitOperation;
    import org.springframework.data.mongodb.core.aggregation.MatchOperation;
    import org.springframework.data.mongodb.core.aggregation.SkipOperation;
    import org.springframework.data.mongodb.core.index.TextIndexDefinition;
    import org.springframework.data.mongodb.core.index.TextIndexDefinition.TextIndexDefinitionBuilder;
    import org.springframework.data.mongodb.core.index.TextIndexed;
    import org.springframework.data.mongodb.core.mapping.Document;
    import org.springframework.data.mongodb.core.mapping.Field;
    import org.springframework.data.mongodb.core.query.Criteria;
    import org.springframework.data.mongodb.core.query.CriteriaDefinition;
    import org.springframework.data.mongodb.core.query.Query;
    import org.springframework.data.mongodb.core.query.TextCriteria;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import lombok.RequiredArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    
    @RequiredArgsConstructor
    @SpringBootApplication
    @Slf4j
    public class MongoAggregationTestApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(MongoAggregationTestApplication.class, args);
        }
    
        private final MongoTemplate mongoTemplate;
    
        @PostConstruct
        void prepareData() {
            boolean collectionExists = mongoTemplate.collectionExists(Product.COLLECTION_NAME);
    
            log.info("####### product collection exists: {}", collectionExists);
    
            if (!collectionExists) {
                throw new RuntimeException(
                        String.format("Required collection {%s} does not exist", Product.COLLECTION_NAME));
            }
    
            //Adding index manually ------------- This is required for text search on productName
            TextIndexDefinition textIndex = new TextIndexDefinitionBuilder().onField("productName", 1F).build();
            mongoTemplate.indexOps(Product.class).ensureIndex(textIndex);
    
            boolean samplesAlreadyAdded = mongoTemplate
                    .exists(new Query().addCriteria(Criteria.where("brandName").exists(true)), Product.class);
    
            //Uncomment to delete all rows from product collection
            //mongoTemplate.getCollection(Product.COLLECTION_NAME).deleteMany(new BsonDocument());
    
            if (!samplesAlreadyAdded) {
                for (int i = 1; i <= 5; i++) {
                    //adds 3 words in productName
                    //product name term1
                    String productName = "product name term" + i;
    
                    Product product = new Product(null, "ACTIVE", productName, "BRAND" + i, "CATEGORY" + i,
                            "SUB_CATEGORY" + 1);
    
                    mongoTemplate.save(product);
    
                    log.info("Saving sample product to database: {}", product);
                }
            } else {
                log.info("Skipping sample insertion as they're already in DB");
            }
        }
    }
    
    @Slf4j
    @RestController
    @RequiredArgsConstructor
    @Validated
    class ProductController {
        private final MongoTemplate mongoTemplate;
    
        //JSR 303 validations are returning 500 when validation fails, instead of 400. Will look into it later
        /**
         * Invoke using follwing command
         * <p>
         * <code>http://localhost:8080/products?productName=product&brandName=BRAND1&categoryName=CATEGORY2&subCategoryName=SUB_CATEGORY3&pageNumber=0&pageSize=10</code>
         * 
         * @param productName
         * @param brandName
         * @param categoryName
         * @param subCategoryName
         * @param pageNumber
         * @param pageSize
         * @return
         */
        @GetMapping("/products")
        public List<Product> getProducts(@RequestParam String productName, @RequestParam String brandName,
                @RequestParam String categoryName, @RequestParam String subCategoryName,
                @RequestParam @Min(0) int pageNumber, @RequestParam @Min(1) @Max(100) int pageSize) {
    
            log.info(
                    "Request parameters: productName: {}, brandName: {}, categoryName: {}, subCategoryName: {}, pageNumber: {}, pageSize: {}",
                    productName, brandName, categoryName, subCategoryName, pageNumber, pageSize);
            //Query Start
    
            TextCriteria productNameTextCriteria = new TextCriteria().matchingAny(productName).caseSensitive(false);
            TextCriteriaHack textCriteriaHack = new TextCriteriaHack();
            textCriteriaHack.addCriteria(productNameTextCriteria);
    
            //Needs this hack to combine TextCriteria with Criteria in a single query
            //See TextCriteriaHack for details
            MatchOperation productNameTextMatch = new MatchOperation(textCriteriaHack);
    
            //Exact match
            Criteria brandNameMatch = Criteria.where("brandName").is(brandName);
            Criteria categoryNameMatch = Criteria.where("categoryName").is(categoryName);
            Criteria subCategoryNameMatch = Criteria.where("subCategoryName").is(subCategoryName);
    
            MatchOperation orMatch = Aggregation
                    .match(new Criteria().orOperator(brandNameMatch, categoryNameMatch, subCategoryNameMatch));
    
            //Pagination setup
            SkipOperation skip = Aggregation.skip((long) pageNumber * pageSize);
            LimitOperation limit = Aggregation.limit(pageSize);
    
            Aggregation aggregation = Aggregation.newAggregation(productNameTextMatch, orMatch, skip, limit);
    
            //Query end
    
            //Query execution
            AggregationResults<Product> aggregateResults = mongoTemplate.aggregate(aggregation, Product.COLLECTION_NAME,
                    Product.class);
    
            List<Product> products = new ArrayList<>();
    
            aggregateResults.iterator().forEachRemaining(products::add);
    
            log.info("Found products: {}", products);
    
            return products;
        }
    }
    
    @Data
    @Document(Product.COLLECTION_NAME)
    @NoArgsConstructor
    @AllArgsConstructor
    class Product {
        static final String COLLECTION_NAME = "product";
    
        @Id
        @Field("_id")
        private String id;
    
        @Field("status")
        private String status;
    
        @TextIndexed
        @Field("productName")
        private String productName;
    
        @Field("brandName")
        private String brandName;
    
        @Field("categoryName")
        private String categoryName;
    
        @Field("subCategoryName")
        private String subCategoryName;
    }
    
    /**
     * https://stackoverflow.com/a/29925876 There is no way to combine
     * CriteriaDefinition and Criteria in one query This hack converts
     * CriteriaDefinition to Query which can be converted to Criteria
     */
    class TextCriteriaHack extends Query implements CriteriaDefinition {
        @Override
        public org.bson.Document getCriteriaObject() {
            return this.getQueryObject();
        }
    
        @Override
        public String getKey() {
            return null;
        }
    }
    

    Here’s the query that’s being executed by /products, I got it from MongoTemplate logs

    [
        {
            "$match": {
                "$text": {
                    "$search": "name",
                    "$caseSensitive": false
                }
            }
        },
        {
            "$match": {
                "$or": [
                    {
                        "brandName": "BRAND1"
                    },
                    {
                        "categoryName": "CATEGORY2"
                    },
                    {
                        "subCategoryName": "SUB_CATEGORY3"
                    }
                ]
            }
        },
        {
            "$skip": 0
        },
        {
            "$limit": 1
        }
    ]
    

    Here’s log contents, after a few requests have been fired

    2022-10-06 04:50:01.209  INFO 26472 --- [           main] c.e.MongoAggregationTestApplication      : No active profile set, falling back to 1 default profile: "default"
    2022-10-06 04:50:01.770  INFO 26472 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data MongoDB repositories in DEFAULT mode.
    2022-10-06 04:50:01.780  INFO 26472 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 6 ms. Found 0 MongoDB repository interfaces.
    2022-10-06 04:50:02.447  INFO 26472 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
    2022-10-06 04:50:02.456  INFO 26472 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
    2022-10-06 04:50:02.456  INFO 26472 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.65]
    2022-10-06 04:50:02.531  INFO 26472 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
    2022-10-06 04:50:02.531  INFO 26472 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1277 ms
    2022-10-06 04:50:02.679  INFO 26472 --- [           main] org.mongodb.driver.client                : MongoClient with metadata {"driver": {"name": "mongo-java-driver|sync|spring-boot", "version": "4.6.1"}, "os": {"type": "Windows", "name": "Windows 10", "architecture": "amd64", "version": "10.0"}, "platform": "Java/OpenLogic-OpenJDK/1.8.0-262-b10"} created with settings MongoClientSettings{readPreference=primary, writeConcern=WriteConcern{w=null, wTimeout=null ms, journal=null}, retryWrites=true, retryReads=true, readConcern=ReadConcern{level=null}, credential=null, streamFactoryFactory=null, commandListeners=[], codecRegistry=ProvidersCodecRegistry{codecProviders=[ValueCodecProvider{}, BsonValueCodecProvider{}, DBRefCodecProvider{}, DBObjectCodecProvider{}, DocumentCodecProvider{}, IterableCodecProvider{}, MapCodecProvider{}, GeoJsonCodecProvider{}, GridFSFileCodecProvider{}, Jsr310CodecProvider{}, JsonObjectCodecProvider{}, BsonCodecProvider{}, EnumCodecProvider{}, com.mongodb.Jep395RecordCodecProvider@22bd2039]}, clusterSettings={hosts=[localhost:27017], srvServiceName=mongodb, mode=SINGLE, requiredClusterType=UNKNOWN, requiredReplicaSetName='null', serverSelector='null', clusterListeners='[]', serverSelectionTimeout='30000 ms', localThreshold='30000 ms'}, socketSettings=SocketSettings{connectTimeoutMS=10000, readTimeoutMS=0, receiveBufferSize=0, sendBufferSize=0}, heartbeatSocketSettings=SocketSettings{connectTimeoutMS=10000, readTimeoutMS=10000, receiveBufferSize=0, sendBufferSize=0}, connectionPoolSettings=ConnectionPoolSettings{maxSize=100, minSize=0, maxWaitTimeMS=120000, maxConnectionLifeTimeMS=0, maxConnectionIdleTimeMS=0, maintenanceInitialDelayMS=0, maintenanceFrequencyMS=60000, connectionPoolListeners=[], maxConnecting=2}, serverSettings=ServerSettings{heartbeatFrequencyMS=10000, minHeartbeatFrequencyMS=500, serverListeners='[]', serverMonitorListeners='[]'}, sslSettings=SslSettings{enabled=false, invalidHostNameAllowed=false, context=null}, applicationName='null', compressorList=[], uuidRepresentation=JAVA_LEGACY, serverApi=null, autoEncryptionSettings=null, contextProvider=null}
    2022-10-06 04:50:02.725  INFO 26472 --- [localhost:27017] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:1, serverValue:121}] to localhost:27017
    2022-10-06 04:50:02.725  INFO 26472 --- [localhost:27017] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:2, serverValue:122}] to localhost:27017
    2022-10-06 04:50:02.726  INFO 26472 --- [localhost:27017] org.mongodb.driver.cluster               : Monitor thread successfully connected to server with description ServerDescription{address=localhost:27017, type=STANDALONE, state=CONNECTED, ok=true, minWireVersion=0, maxWireVersion=13, maxDocumentSize=16777216, logicalSessionTimeoutMinutes=30, roundTripTimeNanos=48972600}
    2022-10-06 04:50:02.922  INFO 26472 --- [           main] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:3, serverValue:123}] to localhost:27017
    2022-10-06 04:50:02.933  INFO 26472 --- [           main] c.e.MongoAggregationTestApplication      : ####### product collection exists: true
    2022-10-06 04:50:02.957 DEBUG 26472 --- [           main] o.s.data.mongodb.core.MongoTemplate      : Executing count: { "brandName" : { "$exists" : true}} in collection: product
    2022-10-06 04:50:02.977 DEBUG 26472 --- [           main] o.s.data.mongodb.core.MongoTemplate      : Saving Document containing fields: [status, productName, brandName, categoryName, subCategoryName, _class]
    2022-10-06 04:50:02.993  INFO 26472 --- [           main] c.e.MongoAggregationTestApplication      : Saving sample product to database: Product(id=633e1122297cce382aea07d4, status=ACTIVE, productName=product name term1, brandName=BRAND1, categoryName=CATEGORY1, subCategoryName=SUB_CATEGORY1)
    2022-10-06 04:50:02.993 DEBUG 26472 --- [           main] o.s.data.mongodb.core.MongoTemplate      : Saving Document containing fields: [status, productName, brandName, categoryName, subCategoryName, _class]
    2022-10-06 04:50:02.995  INFO 26472 --- [           main] c.e.MongoAggregationTestApplication      : Saving sample product to database: Product(id=633e1122297cce382aea07d5, status=ACTIVE, productName=product name term2, brandName=BRAND2, categoryName=CATEGORY2, subCategoryName=SUB_CATEGORY1)
    2022-10-06 04:50:02.995 DEBUG 26472 --- [           main] o.s.data.mongodb.core.MongoTemplate      : Saving Document containing fields: [status, productName, brandName, categoryName, subCategoryName, _class]
    2022-10-06 04:50:02.996  INFO 26472 --- [           main] c.e.MongoAggregationTestApplication      : Saving sample product to database: Product(id=633e1122297cce382aea07d6, status=ACTIVE, productName=product name term3, brandName=BRAND3, categoryName=CATEGORY3, subCategoryName=SUB_CATEGORY1)
    2022-10-06 04:50:02.996 DEBUG 26472 --- [           main] o.s.data.mongodb.core.MongoTemplate      : Saving Document containing fields: [status, productName, brandName, categoryName, subCategoryName, _class]
    2022-10-06 04:50:02.997  INFO 26472 --- [           main] c.e.MongoAggregationTestApplication      : Saving sample product to database: Product(id=633e1122297cce382aea07d7, status=ACTIVE, productName=product name term4, brandName=BRAND4, categoryName=CATEGORY4, subCategoryName=SUB_CATEGORY1)
    2022-10-06 04:50:02.997 DEBUG 26472 --- [           main] o.s.data.mongodb.core.MongoTemplate      : Saving Document containing fields: [status, productName, brandName, categoryName, subCategoryName, _class]
    2022-10-06 04:50:02.998  INFO 26472 --- [           main] c.e.MongoAggregationTestApplication      : Saving sample product to database: Product(id=633e1122297cce382aea07d8, status=ACTIVE, productName=product name term5, brandName=BRAND5, categoryName=CATEGORY5, subCategoryName=SUB_CATEGORY1)
    2022-10-06 04:50:03.310  INFO 26472 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
    2022-10-06 04:50:03.318  INFO 26472 --- [           main] c.e.MongoAggregationTestApplication      : Started MongoAggregationTestApplication in 2.446 seconds (JVM running for 2.802)
    2022-10-06 04:50:17.447  INFO 26472 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
    2022-10-06 04:50:17.447  INFO 26472 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
    2022-10-06 04:50:17.448  INFO 26472 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
    2022-10-06 04:50:17.511  INFO 26472 --- [nio-8080-exec-1] com.example.ProductController            : Request parameters: productName: product, brandName: BRAND1, categoryName: CATEGORY2, subCategoryName: SUB_CATEGORY3, pageNumber: 0, pageSize: 10
    2022-10-06 04:50:17.517 DEBUG 26472 --- [nio-8080-exec-1] o.s.data.mongodb.core.MongoTemplate      : Executing aggregation: [{ "$match" : { "$text" : { "$search" : "product", "$caseSensitive" : false}}}, { "$match" : { "$or" : [{ "brandName" : "BRAND1"}, { "categoryName" : "CATEGORY2"}, { "subCategoryName" : "SUB_CATEGORY3"}]}}, { "$skip" : 0}, { "$limit" : 10}] in collection product
    2022-10-06 04:50:17.527  INFO 26472 --- [nio-8080-exec-1] com.example.ProductController            : Found products: [Product(id=633e1122297cce382aea07d5, status=ACTIVE, productName=product name term2, brandName=BRAND2, categoryName=CATEGORY2, subCategoryName=SUB_CATEGORY1), Product(id=633e1122297cce382aea07d4, status=ACTIVE, productName=product name term1, brandName=BRAND1, categoryName=CATEGORY1, subCategoryName=SUB_CATEGORY1)]
    2022-10-06 04:50:23.235  INFO 26472 --- [nio-8080-exec-2] com.example.ProductController            : Request parameters: productName: product, brandName: BRAND1, categoryName: CATEGORY2, subCategoryName: SUB_CATEGORY3, pageNumber: 0, pageSize: 1
    2022-10-06 04:50:23.236 DEBUG 26472 --- [nio-8080-exec-2] o.s.data.mongodb.core.MongoTemplate      : Executing aggregation: [{ "$match" : { "$text" : { "$search" : "product", "$caseSensitive" : false}}}, { "$match" : { "$or" : [{ "brandName" : "BRAND1"}, { "categoryName" : "CATEGORY2"}, { "subCategoryName" : "SUB_CATEGORY3"}]}}, { "$skip" : 0}, { "$limit" : 1}] in collection product
    2022-10-06 04:50:23.238  INFO 26472 --- [nio-8080-exec-2] com.example.ProductController            : Found products: [Product(id=633e1122297cce382aea07d5, status=ACTIVE, productName=product name term2, brandName=BRAND2, categoryName=CATEGORY2, subCategoryName=SUB_CATEGORY1)]
    2022-10-06 04:50:28.891  INFO 26472 --- [nio-8080-exec-3] com.example.ProductController            : Request parameters: productName: product, brandName: BRAND1, categoryName: CATEGORY2, subCategoryName: SUB_CATEGORY3, pageNumber: 0, pageSize: 10
    2022-10-06 04:50:28.892 DEBUG 26472 --- [nio-8080-exec-3] o.s.data.mongodb.core.MongoTemplate      : Executing aggregation: [{ "$match" : { "$text" : { "$search" : "product", "$caseSensitive" : false}}}, { "$match" : { "$or" : [{ "brandName" : "BRAND1"}, { "categoryName" : "CATEGORY2"}, { "subCategoryName" : "SUB_CATEGORY3"}]}}, { "$skip" : 0}, { "$limit" : 10}] in collection product
    2022-10-06 04:50:28.894  INFO 26472 --- [nio-8080-exec-3] com.example.ProductController            : Found products: [Product(id=633e1122297cce382aea07d5, status=ACTIVE, productName=product name term2, brandName=BRAND2, categoryName=CATEGORY2, subCategoryName=SUB_CATEGORY1), Product(id=633e1122297cce382aea07d4, status=ACTIVE, productName=product name term1, brandName=BRAND1, categoryName=CATEGORY1, subCategoryName=SUB_CATEGORY1)]
    2022-10-06 04:50:33.354  INFO 26472 --- [nio-8080-exec-4] com.example.ProductController            : Request parameters: productName: term3, brandName: BRAND1, categoryName: CATEGORY2, subCategoryName: SUB_CATEGORY3, pageNumber: 0, pageSize: 10
    2022-10-06 04:50:33.355 DEBUG 26472 --- [nio-8080-exec-4] o.s.data.mongodb.core.MongoTemplate      : Executing aggregation: [{ "$match" : { "$text" : { "$search" : "term3", "$caseSensitive" : false}}}, { "$match" : { "$or" : [{ "brandName" : "BRAND1"}, { "categoryName" : "CATEGORY2"}, { "subCategoryName" : "SUB_CATEGORY3"}]}}, { "$skip" : 0}, { "$limit" : 10}] in collection product
    2022-10-06 04:50:33.356  INFO 26472 --- [nio-8080-exec-4] com.example.ProductController            : Found products: []
    2022-10-06 04:50:36.667  INFO 26472 --- [nio-8080-exec-5] com.example.ProductController            : Request parameters: productName: term2, brandName: BRAND1, categoryName: CATEGORY2, subCategoryName: SUB_CATEGORY3, pageNumber: 0, pageSize: 10
    2022-10-06 04:50:36.667 DEBUG 26472 --- [nio-8080-exec-5] o.s.data.mongodb.core.MongoTemplate      : Executing aggregation: [{ "$match" : { "$text" : { "$search" : "term2", "$caseSensitive" : false}}}, { "$match" : { "$or" : [{ "brandName" : "BRAND1"}, { "categoryName" : "CATEGORY2"}, { "subCategoryName" : "SUB_CATEGORY3"}]}}, { "$skip" : 0}, { "$limit" : 10}] in collection product
    2022-10-06 04:50:36.669  INFO 26472 --- [nio-8080-exec-5] com.example.ProductController            : Found products: [Product(id=633e1122297cce382aea07d5, status=ACTIVE, productName=product name term2, brandName=BRAND2, categoryName=CATEGORY2, subCategoryName=SUB_CATEGORY1)]
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search