// [END vision_product_search_create_reference_image]

        // [START vision_product_search_list_reference_images]
        private static int ListReferenceImagesOfProduct(ListReferenceImagesOptions opts)
        {
            var client  = ProductSearchClient.Create();
            var request = new ListReferenceImagesRequest
            {
                // Get the full path of the product.
                ParentAsProductName = new ProductName(opts.ProjectID,
                                                      opts.ComputeRegion,
                                                      opts.ProductID)
            };

            var referenceImages = client.ListReferenceImages(request);

            foreach (var referenceImage in referenceImages)
            {
                var referenceImageID = referenceImage.Name.Split("/").Last();
                Console.WriteLine($"Reference image name: {referenceImage.Name}");
                Console.WriteLine($"Reference image id: {referenceImageID}");
                Console.WriteLine($"Reference image URI: {referenceImage.Uri}");
                Console.WriteLine("Reference image bounding polygons:");
                Console.WriteLine($"\t{referenceImage.BoundingPolys.ToString()}");
            }

            return(0);
        }
        public async Task <IEnumerable <Target> > GetTargets(string targetSetId, int page, int pageSize)
        {
            GoogleCredential cred = this.CreateCredentials();
            var channel           = new Channel(ProductSearchClient.DefaultEndpoint.Host, ProductSearchClient.DefaultEndpoint.Port, cred.ToChannelCredentials());

            try
            {
                var client = ProductSearchClient.Create(channel);

                ListProductsInProductSetRequest request = new ListProductsInProductSetRequest
                {
                    ProductSetName = new ProductSetName(this.options.Value.ProjectId, this.options.Value.LocationId, targetSetId),
                    PageSize       = pageSize,
                };

                PagedAsyncEnumerable <ListProductsInProductSetResponse, Product> response = client.ListProductsInProductSetAsync(request);
                IEnumerable <Product> products = await response.AsAsyncEnumerable().ToArray();

                IEnumerable <Target> targets = await Task.WhenAll(products.Select(p => this.LoadReferenceImagesAndMapToTarget(client, p, pageSize)));

                return(targets);
            }
            finally
            {
                await channel.ShutdownAsync();
            }
        }
예제 #3
0
        // [END vision_product_search_add_product_to_product_set]

        // [START vision_product_search_list_products_in_product_set]
        private static int ListProductsInProductSet(ListProductsInProductSetOptions opts)
        {
            var client  = ProductSearchClient.Create();
            var request = new ListProductsInProductSetRequest
            {
                // Get the full path of the product set.
                ProductSetName = new ProductSetName(opts.ProjectID,
                                                    opts.ComputeRegion,
                                                    opts.ProductSetId)
            };

            var products = client.ListProductsInProductSet(request);

            Console.WriteLine("Products in product set:");
            foreach (var product in products)
            {
                Console.WriteLine($"Product name: {product.Name}");
                Console.WriteLine($"Product id: {product.Name.Split("/").Last()}");
                Console.WriteLine($"Product display name: {product.DisplayName}");
                Console.WriteLine($"Product description: {product.Description}");
                Console.WriteLine($"Product category: {product.ProductCategory}");
                Console.WriteLine($"Product labels:");
                foreach (var label in product.ProductLabels)
                {
                    Console.WriteLine($"Label: {label}");
                }
            }

            return(0);
        }
예제 #4
0
        // [END vision_product_search_list_products]

        // [START vision_product_search_get_product]
        private static int GetProduct(GetProductOptions opts)
        {
            var client  = ProductSearchClient.Create();
            var request = new GetProductRequest
            {
                // Get the full path of the product.
                ProductName = new ProductName(opts.ProjectID,
                                              opts.ComputeRegion,
                                              opts.ProductID)
            };

            var product = client.GetProduct(request);

            var productId = product.Name.Split("/").Last();

            Console.WriteLine($"\nProduct name: {product.Name}");
            Console.WriteLine($"Product id: {productId}");
            Console.WriteLine($"Product display name: {product.DisplayName}");
            Console.WriteLine($"Product category: {product.ProductCategory}");
            Console.WriteLine($"Product labels:");
            foreach (var label in product.ProductLabels)
            {
                Console.WriteLine($"\tLabel: {label.ToString()}");
            }
            return(0);
        }
        public async Task DeleteTarget(string targetSetId, string targetId)
        {
            GoogleCredential cred = this.CreateCredentials();
            var channel           = new Channel(ProductSearchClient.DefaultEndpoint.Host, ProductSearchClient.DefaultEndpoint.Port, cred.ToChannelCredentials());

            try
            {
                var client  = ProductSearchClient.Create(channel);
                var storage = await StorageClient.CreateAsync(cred);

                IEnumerable <Google.Cloud.Vision.V1.ReferenceImage> referenceImages = await this.GetReferenceImages(client, targetId, 100);

                await Task.WhenAll(referenceImages.Select(async r =>
                {
                    await this.DeleteReferenceImage(client, targetId, r.ReferenceImageName.ReferenceImageId);
                    await this.DeleteFile(storage, this.options.Value.StorageBucketName, r.ReferenceImageName.ReferenceImageId);
                }));

                await this.RemoveProductFromProductSet(client, targetSetId, targetId);

                await this.DeleteProduct(client, targetId);
            }
            finally
            {
                await channel.ShutdownAsync();
            }
        }
예제 #6
0
        // [END vision_product_search_create_product]

        // [START vision_product_search_list_products]
        private static int ListProducts(ListProductsOptions opts)
        {
            var client  = ProductSearchClient.Create();
            var request = new ListProductsRequest
            {
                // A resource that represents Google Cloud Platform location.
                ParentAsLocationName = new LocationName(opts.ProjectID,
                                                        opts.ComputeRegion)
            };

            var products = client.ListProducts(request);

            foreach (var product in products)
            {
                var productId = product.Name.Split("/").Last();
                Console.WriteLine($"\nProduct name: {product.Name}");
                Console.WriteLine($"Product id: {productId}");
                Console.WriteLine($"Product display name: {product.DisplayName}");
                Console.WriteLine($"Product category: {product.ProductCategory}");
                Console.WriteLine($"Product labels:");
                foreach (var label in product.ProductLabels)
                {
                    Console.WriteLine($"\tLabel: {label.ToString()}");
                }
            }
            return(0);
        }
        public async Task <Target> CreateTarget(string displayName, string description, IReadOnlyDictionary <string, string> labels, byte[] referenceImageBinaries)
        {
            GoogleCredential cred = this.CreateCredentials();
            var channel           = new Channel(ProductSearchClient.DefaultEndpoint.Host, ProductSearchClient.DefaultEndpoint.Port, cred.ToChannelCredentials());

            try
            {
                var client  = ProductSearchClient.Create(channel);
                var storage = await StorageClient.CreateAsync(cred);

                string productId            = Guid.NewGuid().ToString();
                var    createProductOptions = new CreateProductOptions
                {
                    ProjectID       = this.options.Value.ProjectId,
                    ComputeRegion   = this.options.Value.LocationId,
                    ProductID       = productId,
                    ProductCategory = "apparel",
                    DisplayName     = displayName,
                    Description     = description,
                    ProductLabels   = labels,
                };
                Product product = await this.CreateProduct(client, createProductOptions);

                var addProductOptions = new AddProductToProductSetOptions
                {
                    ProjectID     = this.options.Value.ProjectId,
                    ComputeRegion = this.options.Value.LocationId,
                    ProductID     = product.ProductName.ProductId,
                    ProductSetId  = this.options.Value.ProductSetId,
                };
                await this.AddProductToProductSet(client, addProductOptions);

                string referenceImageId = Guid.NewGuid().ToString();
                await this.UploadFile(storage, this.options.Value.StorageBucketName, referenceImageId, referenceImageBinaries);

                var createReferenceImageOptions = new CreateReferenceImageOptions
                {
                    ProjectID         = this.options.Value.ProjectId,
                    ComputeRegion     = this.options.Value.LocationId,
                    ProductID         = product.ProductName.ProductId,
                    ReferenceImageID  = referenceImageId,
                    ReferenceImageURI = $"gs://{this.options.Value.StorageBucketName}/{referenceImageId}",
                };
                Google.Cloud.Vision.V1.ReferenceImage referenceImage = await this.CreateReferenceImage(client, createReferenceImageOptions);

                Target target = this.mapper.Map <Target>(product);
                target.ReferenceImages = new ReferenceImage[] { this.mapper.Map <ReferenceImage>(referenceImage) };

                return(target);
            }
            finally
            {
                await channel.ShutdownAsync();
            }
        }
예제 #8
0
        public ProductSearchClient CreateProductSearchClient()
        {
            var path       = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, System.AppDomain.CurrentDomain.RelativeSearchPath ?? "");
            var credential = GoogleCredential.FromFile($"{path}\\token.json")
                             .CreateScoped(ProductSearchClient.DefaultScopes);
            var channel = new Grpc.Core.Channel(
                ProductSearchClient.DefaultEndpoint.ToString(),
                credential.ToChannelCredentials());

            var imageAnnotatorClient = ProductSearchClient.Create(channel);

            return(imageAnnotatorClient);
        }
        // [END vision_product_search_get_reference_image]

        // [START vision_product_search_delete_reference_image]
        private static int DeleteReferenceImage(DeleteReferenceImageOptions opts)
        {
            var client  = ProductSearchClient.Create();
            var request = new DeleteReferenceImageRequest
            {
                // Get the full path of the reference image.
                ReferenceImageName = new ReferenceImageName(opts.ProjectID,
                                                            opts.ComputeRegion,
                                                            opts.ProductID,
                                                            opts.ReferenceImageID)
            };

            client.DeleteReferenceImage(request);
            Console.WriteLine("Reference image deleted from product.");
            return(0);
        }
예제 #10
0
        // [END vision_product_search_update_product_labels]

        // [START vision_product_search_delete_product]
        private static int DeleteProduct(DeleteProductOptions opts)
        {
            var client  = ProductSearchClient.Create();
            var request = new DeleteProductRequest
            {
                // Get the full path of the product.
                ProductName = new ProductName(opts.ProjectID,
                                              opts.ComputeRegion,
                                              opts.ProductID)
            };

            client.DeleteProduct(request);
            Console.WriteLine("Product deleted.");

            return(0);
        }
        public async Task GetTargetSets()
        {
            GoogleCredential cred = this.CreateCredentials();
            var channel           = new Channel(ProductSearchClient.DefaultEndpoint.Host, ProductSearchClient.DefaultEndpoint.Port, cred.ToChannelCredentials());

            try
            {
                var client = ProductSearchClient.Create(channel);
                // var productSet = await this.GetProductSets(client, 100);

                // productSet.
            }
            finally
            {
                await channel.ShutdownAsync();
            }
        }
        // [END vision_product_search_get_product_set]

        // [START vision_product_search_delete_product_set]
        private static object DeleteProductSet(DeleteProductSetOptions opts)
        {
            var client = ProductSearchClient.Create();
            var request = new DeleteProductSetRequest
            {
                // Get the full path of the product set.
                ProductSetName = new ProductSetName(opts.ProjectID,
                                                    opts.ComputeRegion,
                                                    opts.ProductSetId)
            };

            // Delete the product set.
            client.DeleteProductSet(request);

            Console.WriteLine("Product set deleted.");
            return 0;
        }
        public async Task <Target> GetTarget(string targetId)
        {
            GoogleCredential cred = this.CreateCredentials();
            var channel           = new Channel(ProductSearchClient.DefaultEndpoint.Host, ProductSearchClient.DefaultEndpoint.Port, cred.ToChannelCredentials());

            try
            {
                var     client  = ProductSearchClient.Create(channel);
                Product product = await this.GetProduct(client, targetId);

                return(await this.LoadReferenceImagesAndMapToTarget(client, product, 100));
            }
            finally
            {
                await channel.ShutdownAsync();
            }
        }
예제 #14
0
        // [END vision_product_search_get_product]

        // [START vision_product_search_update_product_labels]
        private static int UpdateProductLabels(UpdateProductLabelsOptions opts)
        {
            var client  = ProductSearchClient.Create();
            var request = new UpdateProductRequest
            {
                Product = new Product
                {
                    // Get the name of the product
                    ProductName = new ProductName(opts.ProjectID,
                                                  opts.ComputeRegion,
                                                  opts.ProductID),
                    // Set the product name, product label, and product display
                    // name. Multiple labels are also supported.
                    ProductLabels =
                    {
                        new Product.Types.KeyValue
                        {
                            Key   = opts.Labels.Split(",").First(),
                            Value = opts.Labels.Split(",").Last()
                        }
                    }
                },
                // Updating only the product_labels field here.
                UpdateMask = new FieldMask
                {
                    Paths = { "product_labels" }
                }
            };

            // This overwrites the product_labels.
            var product = client.UpdateProduct(request);

            var productId = product.Name.Split("/").Last();

            Console.WriteLine($"\nProduct name: {product.Name}");
            Console.WriteLine($"Product id: {productId}");
            Console.WriteLine($"Product display name: {product.DisplayName}");
            Console.WriteLine($"Product category: {product.ProductCategory}");
            Console.WriteLine($"Product labels:");
            foreach (var label in product.ProductLabels)
            {
                Console.WriteLine($"\tLabel: {label.ToString()}");
            }
            return(0);
        }
예제 #15
0
        // [START vision_product_search_import_product_images]
        private static int ImportProductSet(ImportProductSetOptions opts)
        {
            var client  = ProductSearchClient.Create();
            var request = new ImportProductSetsRequest
            {
                // A resource that represents Google Cloud Platform location.
                ParentAsLocationName = new LocationName(opts.ProjectID,
                                                        opts.ComputeRegion),

                // Set the input configuration along with Google Cloud Storage URI
                InputConfig = new ImportProductSetsInputConfig
                {
                    GcsSource = new ImportProductSetsGcsSource
                    {
                        CsvFileUri = opts.GcsUri
                    }
                }
            };
            var response = client.ImportProductSets(request);

            // Synchronous check of operation status
            var completedResponse = response.PollUntilCompleted();

            if (completedResponse.IsCompleted)
            {
                var result = completedResponse.Result;

                foreach (var status in result.Statuses)
                {
                    // Check status of reference image.
                    // `0` is the code for OK in google.rpc.Code.
                    if (status.Code == 0)
                    {
                        Console.WriteLine(result.ReferenceImages);
                    }
                    else
                    {
                        Console.WriteLine("No reference images.");
                    }
                }
            }

            return(0);
        }
예제 #16
0
        // [END vision_product_search_list_products_in_product_set]

        // [START vision_product_search_remove_product_from_product_set]
        private static int RemoveProductFromProductSet(RemoveProductFromProductSetOptions opts)
        {
            var client  = ProductSearchClient.Create();
            var request = new RemoveProductFromProductSetRequest
            {
                // Get the full path of the product.
                ProductAsProductName = new ProductName(opts.ProjectID,
                                                       opts.ComputeRegion,
                                                       opts.ProductID),
                // Get the full path of the product set.
                ProductSetName = new ProductSetName(opts.ProjectID,
                                                    opts.ComputeRegion,
                                                    opts.ProductSetId)
            };

            client.RemoveProductFromProductSet(request);
            Console.WriteLine("Product removed from product set.");
            return(0);
        }
예제 #17
0
        // [END vision_product_search_delete_product]

        // [START vision_product_search_purge_orphan_products]
        private static int PurgeOrphanProducts(PurgeOrphanProductsOptions opts)
        {
            var client = ProductSearchClient.Create();
            var parent = LocationName.Format(opts.ProjectID, opts.ComputeRegion);

            var request = new PurgeProductsRequest
            {
                Parent = parent,
                DeleteOrphanProducts = true,
                Force = true
            };

            // Purge operation is async.
            var operation = client.PurgeProductsAsync(request);

            // wait until long operation to finish.
            operation.Result.PollUntilCompleted();
            Console.WriteLine("Orphan products deleted.");

            return(0);
        }
예제 #18
0
        // [START vision_product_search_add_product_to_product_set]
        private static int AddProductToProductSet(AddProductToProductSetOptions opts)
        {
            var client  = ProductSearchClient.Create();
            var request = new AddProductToProductSetRequest
            {
                // Get the full path of the products
                ProductAsProductName = new ProductName(opts.ProjectID,
                                                       opts.ComputeRegion,
                                                       opts.ProductID),
                // Get the full path of the product set.
                ProductSetName = new ProductSetName(opts.ProjectID,
                                                    opts.ComputeRegion,
                                                    opts.ProductSetId),
            };

            client.AddProductToProductSet(request);

            Console.WriteLine("Product added to product set.");

            return(0);
        }
예제 #19
0
        // [START vision_product_search_create_product]
        private static int CreateProduct(CreateProductOptions opts)
        {
            var client  = ProductSearchClient.Create();
            var request = new CreateProductRequest
            {
                // A resource that represents Google Cloud Platform location.
                ParentAsLocationName = new LocationName(opts.ProjectID,
                                                        opts.ComputeRegion),
                // Set product category and product display name
                Product = new Product
                {
                    DisplayName     = opts.DisplayName,
                    ProductCategory = opts.ProductCategory
                },
                ProductId = opts.ProductID
            };

            // The response is the product with the `name` field populated.
            var product = client.CreateProduct(request);

            Console.WriteLine($"Product name: {product.Name}");
            return(0);
        }
        public async Task CreateTargetSet(string targetSetId, string displayName)
        {
            GoogleCredential cred = this.CreateCredentials();
            var channel           = new Channel(ProductSearchClient.DefaultEndpoint.Host, ProductSearchClient.DefaultEndpoint.Port, cred.ToChannelCredentials());

            try
            {
                var client = ProductSearchClient.Create(channel);

                var createProductSetOptions = new CreateProductSetsOptions
                {
                    ProjectID             = this.options.Value.ProjectId,
                    ComputeRegion         = this.options.Value.LocationId,
                    ProductSetId          = targetSetId,
                    ProductSetDisplayName = displayName,
                };
                var productSet = await this.CreateProductSet(client, createProductSetOptions);
            }
            finally
            {
                await channel.ShutdownAsync();
            }
        }
        // [END vision_product_search_list_reference_images]

        // [START vision_product_search_get_reference_image]
        private static int GetReferenceImage(GetReferenceImageOptions opts)
        {
            var client  = ProductSearchClient.Create();
            var request = new GetReferenceImageRequest
            {
                // Get the full path of the reference image.
                ReferenceImageName = new ReferenceImageName(opts.ProjectID,
                                                            opts.ComputeRegion,
                                                            opts.ProductID,
                                                            opts.ReferenceImageID)
            };

            var referenceImage = client.GetReferenceImage(request);

            var referenceImageID = referenceImage.Name.Split("/").Last();

            Console.WriteLine($"Reference image name: {referenceImage.Name}");
            Console.WriteLine($"Reference image id: {referenceImageID}");
            Console.WriteLine($"Reference image URI: {referenceImage.Uri}");
            Console.WriteLine("Reference image bounding polygons:");
            Console.WriteLine($"\t{referenceImage.BoundingPolys.ToString()}");
            return(0);
        }
예제 #22
0
        // [END vision_product_search_remove_product_from_product_set]

        // [START vision_product_search_purge_products_in_product_set]
        private static int PurgeProductsInProductSet(PurgeProductsInProductSetOptions opts)
        {
            var client = ProductSearchClient.Create();
            var parent = LocationName.Format(opts.ProjectID, opts.ComputeRegion);
            var productSetPurgeConfig = new ProductSetPurgeConfig
            {
                ProductSetId = opts.ProductSetId
            };
            var req = new PurgeProductsRequest
            {
                Parent = parent,
                ProductSetPurgeConfig = productSetPurgeConfig,
                Force = true
            };

            var response = client.PurgeProductsAsync(req);

            // wait until it finishes
            response.Result.PollUntilCompleted();

            Console.WriteLine("Products removed from product set.");
            return(0);
        }
        // [END vision_product_search_list_product_sets]

        // [START vision_product_search_get_product_set]
        private static object GetProductSet(GetProductSetOptions opts)
        {
            var client = ProductSearchClient.Create();
            var request = new GetProductSetRequest
            {
                // Get the full path of the product set.
                ProductSetName = new ProductSetName(opts.ProjectID,
                                                    opts.ComputeRegion,
                                                    opts.ProductSetId)
            };

            // Get the complete detail of the product set.
            var productSet = client.GetProductSet(request);

            var id = productSet.Name.Split("/").Last();
            Console.WriteLine($"Product set name: {productSet.DisplayName}");
            Console.WriteLine($"Product set ID: {id}");
            Console.WriteLine($"Product set index time:");
            Console.WriteLine($"\tseconds: {productSet.IndexTime.Seconds}");
            Console.WriteLine($"\tnanos: {productSet.IndexTime.Nanos}");

            return 0;
        }
        // [START vision_product_search_create_reference_image]
        private static int CreateReferenceImage(CreateReferenceImageOptions opts)
        {
            var client  = ProductSearchClient.Create();
            var request = new CreateReferenceImageRequest
            {
                // Get the full path of the product.
                ParentAsProductName = new ProductName(opts.ProjectID,
                                                      opts.ComputeRegion,
                                                      opts.ProductID),
                ReferenceImageId = opts.ReferenceImageID,
                // Create a reference image.
                ReferenceImage = new ReferenceImage
                {
                    Uri = opts.ReferenceImageURI
                }
            };

            var referenceImage = client.CreateReferenceImage(request);

            Console.WriteLine($"Reference image name: {referenceImage.Name}");
            Console.WriteLine($"Reference image URI: {referenceImage.Uri}");

            return(0);
        }
        // [END vision_product_search_create_product_set]

        // [START vision_product_search_list_product_sets]
        private static object ListProductsSet(ListProductSetsOptions opts)
        {
            var client = ProductSearchClient.Create();
            var request = new ListProductSetsRequest
            {
                // A resource that represents Google Cloud Platform location
                ParentAsLocationName = new LocationName(opts.ProjectID, opts.ComputeRegion)
            };

            // List all the product sets available in the region.
            var response = client.ListProductSets(request);

            foreach (var productSet in response)
            {
                var id = productSet.Name.Split("/").Last();
                Console.WriteLine($"Product set name: {productSet.DisplayName}");
                Console.WriteLine($"Product set ID: {id}");
                Console.WriteLine($"Product set index time:");
                Console.WriteLine($"\tseconds: {productSet.IndexTime.Seconds}");
                Console.WriteLine($"\tnanos: {productSet.IndexTime.Nanos}");
            }

            return 0;
        }
        // [START vision_product_search_create_product_set]
        private static object CreateProductSet(CreateProductSetsOptions opts)
        {
            var client = ProductSearchClient.Create();

            // Create a product set with the product set specification in the region.
            var request = new CreateProductSetRequest
            {
                // A resource that represents Google Cloud Platform location
                ParentAsLocationName = new LocationName(opts.ProjectID,
                                                        opts.ComputeRegion),
                ProductSetId = opts.ProductSetId,
                ProductSet = new ProductSet
                {
                    DisplayName = opts.ProductSetDisplayName
                }
            };

            // The response is the product set with the `name` populated
            var response = client.CreateProductSet(request);

            Console.WriteLine($"Product set name: {response.DisplayName}");

            return 0;
        }
예제 #27
0
        static int Main(string[] args)
        {
            if (args.Length != 2)
            {
                Console.WriteLine("Arguments: <directory containing product.json> <project ID>");
                return(1);
            }
            string directory = args[0];
            var    json      = File.ReadAllText(Path.Combine(directory, "products.json"));
            var    products  = JsonConvert.DeserializeObject <List <JsonProduct> >(json);

            // Default the location and bucket so it's easily predictable in tests.
            string projectId    = args[1];
            string locationId   = "us-west1";
            string bucketName   = $"{projectId}_product_search_test";
            string bucketUri    = $"gs://{bucketName}";
            string productSetId = $"{projectId}_product_search_test";
            var    location     = LocationName.FromProjectLocation(projectId, locationId);

            var storageClient       = StorageClient.Create();
            var productSearchClient = ProductSearchClient.Create();

            // Create the GCS bucket and upload the images
            storageClient.CreateBucket(projectId, bucketName);
            foreach (var product in products)
            {
                using (var stream = File.OpenRead(Path.Combine(directory, product.Image)))
                {
                    // TODO: Autodetect the mime type if we ever have non-JPEG images
                    storageClient.UploadObject(bucketName, product.Image, "image/jpeg", stream);
                }
            }

            // Create the product set
            var createProductSetRequest = new CreateProductSetRequest
            {
                ParentAsLocationName = location,
                ProductSetId         = productSetId,
                ProductSet           = new ProductSet
                {
                    DisplayName = "Product set for testing"
                }
            };

            // Add the products. Each product needs to be:
            // - Created
            // - Added to the product set
            // - Associated with a reference image
            var productSetResource = productSearchClient.CreateProductSet(createProductSetRequest);

            foreach (var product in products)
            {
                var createProductRequest = new CreateProductRequest
                {
                    ParentAsLocationName = location,
                    ProductId            = product.Id,
                    Product = new Product
                    {
                        Description     = product.Description,
                        DisplayName     = product.DisplayName,
                        ProductCategory = product.Category,
                        ProductLabels   = { product.Labels.Select(kvp => new Product.Types.KeyValue {
                                Key = kvp.Key, Value = kvp.Value
                            }) }
                    }
                };
                var productResource = productSearchClient.CreateProduct(createProductRequest);
                productSearchClient.AddProductToProductSet(productSetResource.ProductSetName, productResource.ProductName);

                productSearchClient.CreateReferenceImage(productResource.ProductName, new ReferenceImage {
                    Uri = $"{bucketUri}/{product.Image}"
                }, product.Image);
            }
            return(0);
        }